View | Details | Raw Unified | Return to bug 340876 | Differences between
and this patch

Collapse All | Expand All

(-)META-INF/MANIFEST.MF (-1 / +1 lines)
Lines 2-8 Link Here
2
Bundle-ManifestVersion: 2
2
Bundle-ManifestVersion: 2
3
Bundle-Name: %pluginName
3
Bundle-Name: %pluginName
4
Bundle-SymbolicName: org.eclipse.jdt.ui; singleton:=true
4
Bundle-SymbolicName: org.eclipse.jdt.ui; singleton:=true
5
Bundle-Version: 3.7.0.qualifier
5
Bundle-Version: 3.7.1.qualifier
6
Bundle-Activator: org.eclipse.jdt.internal.ui.JavaPlugin
6
Bundle-Activator: org.eclipse.jdt.internal.ui.JavaPlugin
7
Bundle-ActivationPolicy: lazy
7
Bundle-ActivationPolicy: lazy
8
Bundle-Vendor: %providerName
8
Bundle-Vendor: %providerName
(-)ui/org/eclipse/jdt/internal/ui/javaeditor/SpecificContentAssistExecutor.java (-16 / +18 lines)
Lines 7-17 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.javaeditor;
12
package org.eclipse.jdt.internal.ui.javaeditor;
12
13
14
import java.util.ArrayList;
13
import java.util.Collection;
15
import java.util.Collection;
16
import java.util.HashSet;
14
import java.util.Iterator;
17
import java.util.Iterator;
18
import java.util.Set;
15
19
16
import org.eclipse.core.runtime.Assert;
20
import org.eclipse.core.runtime.Assert;
17
21
Lines 24-31 Link Here
24
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry;
28
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry;
25
29
26
/**
30
/**
27
 * A content assist executor can invoke content assist for a specific proposal category on an editor.
31
 * A content assist executor can invoke content assist for a specific proposal category on an
28
 *
32
 * editor.
33
 * 
29
 * @since 3.2
34
 * @since 3.2
30
 */
35
 */
31
public final class SpecificContentAssistExecutor {
36
public final class SpecificContentAssistExecutor {
Lines 34-40 Link Here
34
39
35
	/**
40
	/**
36
	 * Creates a new executor.
41
	 * Creates a new executor.
37
	 *
42
	 * 
38
	 * @param registry the computer registry to use for the enablement of proposal categories
43
	 * @param registry the computer registry to use for the enablement of proposal categories
39
	 */
44
	 */
40
	public SpecificContentAssistExecutor(CompletionProposalComputerRegistry registry) {
45
	public SpecificContentAssistExecutor(CompletionProposalComputerRegistry registry) {
Lines 45-65 Link Here
45
	/**
50
	/**
46
	 * Invokes content assist on <code>editor</code>, showing only proposals computed by the
51
	 * Invokes content assist on <code>editor</code>, showing only proposals computed by the
47
	 * <code>CompletionProposalCategory</code> with the given <code>categoryId</code>.
52
	 * <code>CompletionProposalCategory</code> with the given <code>categoryId</code>.
48
	 *
53
	 * 
49
	 * @param editor the editor to invoke code assist on
54
	 * @param editor the editor to invoke code assist on
50
	 * @param categoryId the id of the proposal category to show proposals for
55
	 * @param categoryId the id of the proposal category to show proposals for
51
	 */
56
	 */
52
	public void invokeContentAssist(final ITextEditor editor, String categoryId) {
57
	public void invokeContentAssist(final ITextEditor editor, String categoryId) {
53
		Collection<CompletionProposalCategory> categories= fRegistry.getProposalCategories();
58
		Collection<CompletionProposalCategory> categories= fRegistry.getProposalCategories();
54
		boolean[] inclusionState= new boolean[categories.size()];
59
		ArrayList<Set<Integer>> categoriesState= new ArrayList<Set<Integer>>(categories.size());
55
		boolean[] separateState= new boolean[categories.size()];
60
		for (CompletionProposalCategory cat : categories) {
56
		int i= 0;
61
			categoriesState.add(new HashSet<Integer>(cat.getProposalListIndices()));
57
		for (Iterator<CompletionProposalCategory> it= categories.iterator(); it.hasNext(); i++) {
62
			cat.clearProposalListIndices();
58
			CompletionProposalCategory cat= it.next();
63
			if (cat.getId().equals(categoryId))
59
			inclusionState[i]= cat.isIncluded();
64
				cat.addProposalListIndex(Integer.valueOf(0));
60
			cat.setIncluded(cat.getId().equals(categoryId));
61
			separateState[i]= cat.isSeparateCommand();
62
			cat.setSeparateCommand(false);
63
		}
65
		}
64
66
65
		try {
67
		try {
Lines 67-77 Link Here
67
			if (target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS))
69
			if (target != null && target.canDoOperation(ISourceViewer.CONTENTASSIST_PROPOSALS))
68
				target.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
70
				target.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
69
		} finally {
71
		} finally {
70
			i= 0;
72
			int i= 0;
71
			for (Iterator<CompletionProposalCategory> it= categories.iterator(); it.hasNext(); i++) {
73
			for (Iterator<CompletionProposalCategory> it= categories.iterator(); it.hasNext(); i++) {
72
				CompletionProposalCategory cat= it.next();
74
				CompletionProposalCategory cat= it.next();
73
				cat.setIncluded(inclusionState[i]);
75
				cat.clearProposalListIndices();
74
				cat.setSeparateCommand(separateState[i]);
76
				cat.addAllProposalListIndices(categoriesState.get(i));
75
			}
77
			}
76
		}
78
		}
77
	}
79
	}
(-)ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedConfigurationBlock.java (-784 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.preferences;
12
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.HashMap;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
21
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.events.SelectionAdapter;
23
import org.eclipse.swt.events.SelectionEvent;
24
import org.eclipse.swt.graphics.GC;
25
import org.eclipse.swt.graphics.Image;
26
import org.eclipse.swt.layout.GridData;
27
import org.eclipse.swt.layout.GridLayout;
28
import org.eclipse.swt.widgets.Button;
29
import org.eclipse.swt.widgets.Composite;
30
import org.eclipse.swt.widgets.Control;
31
import org.eclipse.swt.widgets.Label;
32
import org.eclipse.swt.widgets.Link;
33
import org.eclipse.swt.widgets.Table;
34
import org.eclipse.swt.widgets.TableColumn;
35
36
import org.eclipse.core.commands.Command;
37
import org.eclipse.core.commands.CommandManager;
38
import org.eclipse.core.commands.IParameter;
39
import org.eclipse.core.commands.Parameterization;
40
import org.eclipse.core.commands.ParameterizedCommand;
41
import org.eclipse.core.commands.common.NotDefinedException;
42
import org.eclipse.core.commands.contexts.ContextManager;
43
44
import org.eclipse.core.runtime.Assert;
45
46
import org.eclipse.jface.bindings.BindingManager;
47
import org.eclipse.jface.bindings.Scheme;
48
import org.eclipse.jface.bindings.TriggerSequence;
49
import org.eclipse.jface.layout.PixelConverter;
50
import org.eclipse.jface.resource.ImageDescriptor;
51
import org.eclipse.jface.resource.JFaceResources;
52
import org.eclipse.jface.viewers.ArrayContentProvider;
53
import org.eclipse.jface.viewers.CheckStateChangedEvent;
54
import org.eclipse.jface.viewers.CheckboxTableViewer;
55
import org.eclipse.jface.viewers.ICheckStateListener;
56
import org.eclipse.jface.viewers.IStructuredSelection;
57
import org.eclipse.jface.viewers.ITableLabelProvider;
58
import org.eclipse.jface.viewers.LabelProvider;
59
import org.eclipse.jface.viewers.ViewerComparator;
60
61
import org.eclipse.ui.PlatformUI;
62
import org.eclipse.ui.commands.ICommandService;
63
import org.eclipse.ui.dialogs.PreferencesUtil;
64
import org.eclipse.ui.keys.IBindingService;
65
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
66
67
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
68
69
import org.eclipse.jdt.core.JavaCore;
70
71
import org.eclipse.jdt.internal.corext.util.Messages;
72
73
import org.eclipse.jdt.ui.PreferenceConstants;
74
75
import org.eclipse.jdt.internal.ui.JavaPlugin;
76
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
77
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory;
78
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry;
79
import org.eclipse.jdt.internal.ui.util.SWTUtil;
80
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
81
82
83
/**
84
 *
85
 * @since 3.2
86
 */
87
final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock {
88
89
	private static final Key PREF_EXCLUDED_CATEGORIES= getJDTUIKey(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
90
	private static final Key PREF_CATEGORY_ORDER= getJDTUIKey(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
91
	private static final Key PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC= getJDTCoreKey(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC);
92
93
	private static Key[] getAllKeys() {
94
		return new Key[] {
95
				PREF_EXCLUDED_CATEGORIES,
96
				PREF_CATEGORY_ORDER,
97
				PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
98
		};
99
	}
100
101
	private final class DefaultTableLabelProvider extends LabelProvider implements ITableLabelProvider {
102
103
		/*
104
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
105
		 */
106
		public Image getColumnImage(Object element, int columnIndex) {
107
			if (columnIndex == 0)
108
				return ((ModelElement) element).getImage();
109
			return null;
110
		}
111
112
		/*
113
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
114
		 */
115
		public String getColumnText(Object element, int columnIndex) {
116
			switch (columnIndex) {
117
	            case 0:
118
	            	return ((ModelElement) element).getName();
119
	            case 1:
120
	            	return ((ModelElement) element).getKeybindingAsString();
121
	            default:
122
	            	Assert.isTrue(false);
123
	            	return null;
124
            }
125
		}
126
127
		/*
128
		 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
129
		 */
130
		@Override
131
		public String getText(Object element) {
132
		    return getColumnText(element, 0); // needed to make the sorter work
133
		}
134
	}
135
136
	private final class SeparateTableLabelProvider extends LabelProvider implements ITableLabelProvider {
137
138
		/*
139
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
140
		 */
141
		public Image getColumnImage(Object element, int columnIndex) {
142
			if (columnIndex == 0)
143
				return ((ModelElement) element).getImage();
144
			return null;
145
		}
146
147
		/*
148
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
149
		 */
150
		public String getColumnText(Object element, int columnIndex) {
151
			switch (columnIndex) {
152
				case 0:
153
					return ((ModelElement) element).getName();
154
				default:
155
					Assert.isTrue(false);
156
				return null;
157
			}
158
		}
159
	}
160
161
	private final Comparator<ModelElement> fCategoryComparator= new Comparator<ModelElement>() {
162
		private int getRank(ModelElement o) {
163
			return o.getRank();
164
		}
165
166
		public int compare(ModelElement o1, ModelElement o2) {
167
			return getRank(o1) - getRank(o2);
168
		}
169
	};
170
171
	private final class PreferenceModel {
172
		private static final int LIMIT= 65535;
173
		private static final String COLON= ":"; //$NON-NLS-1$
174
		private static final String SEPARATOR= "\0"; //$NON-NLS-1$
175
176
		private final List<ModelElement> fElements;
177
		/**
178
		 * The read-only list of elements.
179
		 */
180
		final List<ModelElement> elements;
181
182
		public PreferenceModel(CompletionProposalComputerRegistry registry) {
183
			List<CompletionProposalCategory> categories= registry.getProposalCategories();
184
			fElements= new ArrayList<ModelElement>();
185
			for (Iterator<CompletionProposalCategory> it= categories.iterator(); it.hasNext();) {
186
				CompletionProposalCategory category= it.next();
187
				if (category.hasComputers()) {
188
					fElements.add(new ModelElement(category, this));
189
				}
190
			}
191
			Collections.sort(fElements, fCategoryComparator);
192
			elements= Collections.unmodifiableList(fElements);
193
		}
194
195
        public void moveUp(ModelElement category) {
196
        	int index= fElements.indexOf(category);
197
			if (index > 0) {
198
				ModelElement item= fElements.remove(index);
199
				fElements.add(index - 1, item);
200
				writeOrderPreference(null, false);
201
			}
202
        }
203
204
        public void moveDown(ModelElement category) {
205
        	int index= fElements.indexOf(category);
206
			if (index < fElements.size() - 1) {
207
				ModelElement item= fElements.remove(index);
208
				fElements.add(index + 1, item);
209
				writeOrderPreference(null, false);
210
			}
211
        }
212
213
    	private void writeInclusionPreference(ModelElement changed, boolean isInDefaultCategory) {
214
    		StringBuffer buf= new StringBuffer();
215
    		for (Iterator<ModelElement> it= fElements.iterator(); it.hasNext();) {
216
    			ModelElement item= it.next();
217
    			boolean included= changed == item ? isInDefaultCategory : item.isInDefaultCategory();
218
    			if (!included)
219
    				buf.append(item.getId() + SEPARATOR);
220
    		}
221
222
    		String newValue= buf.toString();
223
    		String oldValue= setValue(PREF_EXCLUDED_CATEGORIES, newValue);
224
    		validateSettings(PREF_EXCLUDED_CATEGORIES, oldValue, newValue);
225
    	}
226
227
    	private void writeOrderPreference(ModelElement changed, boolean isSeparate) {
228
    		StringBuffer buf= new StringBuffer();
229
    		int i= 0;
230
    		for (Iterator<ModelElement> it= fElements.iterator(); it.hasNext(); i++) {
231
    			ModelElement item= it.next();
232
    			boolean separate= changed == item ? isSeparate : item.isSeparateCommand();
233
    			int rank= separate ? i : i + LIMIT;
234
    			buf.append(item.getId() + COLON + rank + SEPARATOR);
235
    		}
236
237
    		String newValue= buf.toString();
238
    		String oldValue= setValue(PREF_CATEGORY_ORDER, newValue);
239
    		validateSettings(PREF_CATEGORY_ORDER, oldValue, newValue);
240
    	}
241
242
243
    	private boolean readInclusionPreference(CompletionProposalCategory cat) {
244
    		String[] ids= getTokens(getValue(PREF_EXCLUDED_CATEGORIES), SEPARATOR);
245
    		for (int i= 0; i < ids.length; i++) {
246
    			if (ids[i].equals(cat.getId()))
247
    				return false;
248
    		}
249
    		return true;
250
    	}
251
252
    	private int readOrderPreference(CompletionProposalCategory cat) {
253
    		String[] sortOrderIds= getTokens(getValue(PREF_CATEGORY_ORDER), SEPARATOR);
254
    		for (int i= 0; i < sortOrderIds.length; i++) {
255
    			String[] idAndRank= getTokens(sortOrderIds[i], COLON);
256
    			if (idAndRank[0].equals(cat.getId()))
257
    				return Integer.parseInt(idAndRank[1]);
258
    		}
259
			return LIMIT - 1;
260
    	}
261
262
        public void update() {
263
			Collections.sort(fElements, fCategoryComparator);
264
        }
265
	}
266
267
	private final class ModelElement {
268
		private final CompletionProposalCategory fCategory;
269
		private final Command fCommand;
270
		private final IParameter fParam;
271
		private final PreferenceModel fPreferenceModel;
272
273
		ModelElement(CompletionProposalCategory category, PreferenceModel model) {
274
			fCategory= category;
275
			ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
276
			fCommand= commandSvc.getCommand("org.eclipse.jdt.ui.specific_content_assist.command"); //$NON-NLS-1$
277
			IParameter type;
278
			try {
279
				type= fCommand.getParameters()[0];
280
			} catch (NotDefinedException x) {
281
				Assert.isTrue(false);
282
				type= null;
283
			}
284
			fParam= type;
285
			fPreferenceModel= model;
286
		}
287
		Image getImage() {
288
			return CodeAssistAdvancedConfigurationBlock.this.getImage(fCategory.getImageDescriptor());
289
		}
290
		String getName() {
291
			return fCategory.getDisplayName();
292
		}
293
		String getKeybindingAsString() {
294
			final Parameterization[] params= { new Parameterization(fParam, fCategory.getId()) };
295
			final ParameterizedCommand pCmd= new ParameterizedCommand(fCommand, params);
296
			String key= getKeyboardShortcut(pCmd);
297
			return key;
298
		}
299
		boolean isInDefaultCategory() {
300
			return fPreferenceModel.readInclusionPreference(fCategory);
301
		}
302
		void setInDefaultCategory(boolean included) {
303
			if (included != isInDefaultCategory())
304
				fPreferenceModel.writeInclusionPreference(this, included);
305
		}
306
		String getId() {
307
			return fCategory.getId();
308
		}
309
		int getRank() {
310
			int rank= getInternalRank();
311
			if (rank > PreferenceModel.LIMIT)
312
				return rank - PreferenceModel.LIMIT;
313
			return rank;
314
		}
315
		void moveUp() {
316
			fPreferenceModel.moveUp(this);
317
		}
318
		void moveDown() {
319
			fPreferenceModel.moveDown(this);
320
		}
321
		private int getInternalRank() {
322
			return fPreferenceModel.readOrderPreference(fCategory);
323
		}
324
		boolean isSeparateCommand() {
325
			return getInternalRank() < PreferenceModel.LIMIT;
326
		}
327
328
		void setSeparateCommand(boolean separate) {
329
			if (separate != isSeparateCommand())
330
				fPreferenceModel.writeOrderPreference(this, separate);
331
		}
332
333
		void update() {
334
			fCategory.setIncluded(isInDefaultCategory());
335
			int rank= getInternalRank();
336
			fCategory.setSortOrder(rank);
337
			fCategory.setSeparateCommand(rank < PreferenceModel.LIMIT);
338
		}
339
	}
340
341
	/** element type: {@link ModelElement}. */
342
	private final PreferenceModel fModel;
343
	private final Map<ImageDescriptor, Image> fImages= new HashMap<ImageDescriptor, Image>();
344
345
	private CheckboxTableViewer fDefaultViewer;
346
	private CheckboxTableViewer fSeparateViewer;
347
	private Button fUpButton;
348
	private Button fDownButton;
349
350
	CodeAssistAdvancedConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer container) {
351
		super(statusListener, null, getAllKeys(), container);
352
		fModel= new PreferenceModel(CompletionProposalComputerRegistry.getDefault());
353
	}
354
355
	/*
356
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
357
	 */
358
	@Override
359
	protected Control createContents(Composite parent) {
360
361
		ScrolledPageContent scrolled= new ScrolledPageContent(parent, SWT.H_SCROLL | SWT.V_SCROLL);
362
363
		scrolled.setExpandHorizontal(true);
364
		scrolled.setExpandVertical(true);
365
366
		Composite composite= new Composite(scrolled, SWT.NONE);
367
		int columns= 2;
368
		GridLayout layout= new GridLayout(columns, false);
369
		layout.marginWidth= 0;
370
		layout.marginHeight= 0;
371
		composite.setLayout(layout);
372
373
374
		createDefaultLabel(composite, columns);
375
		createDefaultViewer(composite, columns);
376
		createKeysLink(composite, columns);
377
378
		createFiller(composite, columns);
379
380
		createSeparateLabel(composite, columns);
381
        createSeparateSection(composite);
382
383
        createFiller(composite, columns);
384
385
		createParameterTimeoutControl(composite, columns);
386
387
		updateControls();
388
		if (fModel.elements.size() > 0) {
389
			fDefaultViewer.getTable().select(0);
390
			fSeparateViewer.getTable().select(0);
391
			handleTableSelection();
392
		}
393
394
		scrolled.setContent(composite);
395
		scrolled.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
396
		return scrolled;
397
	}
398
399
	private void createDefaultLabel(Composite composite, int h_span) {
400
	    final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
401
		final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
402
		ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
403
		String key= getKeyboardShortcut(pCmd);
404
		if (key == null)
405
			key= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_no_shortcut;
406
407
		PixelConverter pixelConverter= new PixelConverter(composite);
408
		int width= pixelConverter.convertWidthInCharsToPixels(40);
409
410
		Label label= new Label(composite, SWT.NONE | SWT.WRAP);
411
		label.setText(Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_page_description, new Object[] { key }));
412
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
413
		gd.widthHint= width;
414
		label.setLayoutData(gd);
415
416
		createFiller(composite, h_span);
417
418
		label= new Label(composite, SWT.NONE | SWT.WRAP);
419
		label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_description);
420
		gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
421
		gd.widthHint= width;
422
		label.setLayoutData(gd);
423
    }
424
425
	private void createDefaultViewer(Composite composite, int h_span) {
426
		fDefaultViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
427
		Table table= fDefaultViewer.getTable();
428
		table.setHeaderVisible(true);
429
		table.setLinesVisible(false);
430
		table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false, h_span, 1));
431
432
		TableColumn nameColumn= new TableColumn(table, SWT.NONE);
433
		nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_category_column_title);
434
		nameColumn.setResizable(false);
435
		TableColumn keyColumn= new TableColumn(table, SWT.NONE);
436
		keyColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title);
437
		keyColumn.setResizable(false);
438
439
		fDefaultViewer.addCheckStateListener(new ICheckStateListener() {
440
			public void checkStateChanged(CheckStateChangedEvent event) {
441
				boolean checked= event.getChecked();
442
				ModelElement element= (ModelElement) event.getElement();
443
				element.setInDefaultCategory(checked);
444
			}
445
		});
446
447
		fDefaultViewer.setContentProvider(new ArrayContentProvider());
448
449
		DefaultTableLabelProvider labelProvider= new DefaultTableLabelProvider();
450
		fDefaultViewer.setLabelProvider(labelProvider);
451
		fDefaultViewer.setInput(fModel.elements);
452
		fDefaultViewer.setComparator(new ViewerComparator()); // sort alphabetically
453
454
		final int ICON_AND_CHECKBOX_WITH= 50;
455
		final int HEADER_MARGIN= 20;
456
		int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
457
		int minKeyWidth= computeWidth(table, keyColumn.getText()) + HEADER_MARGIN;
458
		for (int i= 0; i < fModel.elements.size(); i++) {
459
			minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
460
			minKeyWidth= Math.max(minKeyWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 1)));
461
		}
462
463
		nameColumn.setWidth(minNameWidth);
464
		keyColumn.setWidth(minKeyWidth);
465
	}
466
467
	private void createKeysLink(Composite composite, int h_span) {
468
	    Link link= new Link(composite, SWT.NONE | SWT.WRAP);
469
		link.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_key_binding_hint);
470
		link.addSelectionListener(new SelectionAdapter() {
471
			@Override
472
			public void widgetSelected(SelectionEvent e) {
473
				PreferencesUtil.createPreferenceDialogOn(getShell(), e.text, null, null);
474
			}
475
		});
476
477
		PixelConverter pixelConverter= new PixelConverter(composite);
478
		int width= pixelConverter.convertWidthInCharsToPixels(40);
479
480
		// limit the size of the Link as it would take all it can get
481
		GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
482
		gd.widthHint= width;
483
		link.setLayoutData(gd);
484
    }
485
486
	private void createFiller(Composite composite, int h_span) {
487
	    Label filler= new Label(composite, SWT.NONE);
488
		filler.setVisible(false);
489
		filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, h_span, 1));
490
    }
491
492
	private void createSeparateLabel(Composite composite, int h_span) {
493
		PixelConverter pixelConverter= new PixelConverter(composite);
494
		int width= pixelConverter.convertWidthInCharsToPixels(40);
495
496
		Label label= new Label(composite, SWT.NONE | SWT.WRAP);
497
		label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_description);
498
		GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
499
		gd.widthHint= width;
500
		label.setLayoutData(gd);
501
	}
502
503
	private void createSeparateSection(Composite composite) {
504
		createSeparateViewer(composite);
505
		createButtonList(composite);
506
	}
507
508
	private void createSeparateViewer(Composite composite) {
509
		fSeparateViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
510
		Table table= fSeparateViewer.getTable();
511
		table.setHeaderVisible(false);
512
		table.setLinesVisible(false);
513
		table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1));
514
515
		TableColumn nameColumn= new TableColumn(table, SWT.NONE);
516
		nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title);
517
		nameColumn.setResizable(false);
518
519
		fSeparateViewer.setContentProvider(new ArrayContentProvider());
520
521
		ITableLabelProvider labelProvider= new SeparateTableLabelProvider();
522
		fSeparateViewer.setLabelProvider(labelProvider);
523
		fSeparateViewer.setInput(fModel.elements);
524
525
		final int ICON_AND_CHECKBOX_WITH= 50;
526
		final int HEADER_MARGIN= 20;
527
		int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
528
		for (int i= 0; i < fModel.elements.size(); i++) {
529
			minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
530
		}
531
532
		nameColumn.setWidth(minNameWidth);
533
534
		fSeparateViewer.addCheckStateListener(new ICheckStateListener() {
535
			public void checkStateChanged(CheckStateChangedEvent event) {
536
				boolean checked= event.getChecked();
537
				ModelElement element= (ModelElement) event.getElement();
538
				element.setSeparateCommand(checked);
539
			}
540
		});
541
542
		table.addSelectionListener(new SelectionAdapter() {
543
			@Override
544
			public void widgetSelected(SelectionEvent e) {
545
				handleTableSelection();
546
			}
547
		});
548
549
	}
550
551
	private void createButtonList(Composite parent) {
552
		Composite composite= new Composite(parent, SWT.NONE);
553
		composite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
554
555
		GridLayout layout= new GridLayout();
556
		layout.marginWidth= 0;
557
		layout.marginHeight= 0;
558
		composite.setLayout(layout);
559
560
		fUpButton= new Button(composite, SWT.PUSH | SWT.CENTER);
561
        fUpButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Up);
562
        fUpButton.addSelectionListener(new SelectionAdapter() {
563
        	@Override
564
			public void widgetSelected(SelectionEvent e) {
565
        		int index= getSelectionIndex();
566
        		if (index != -1) {
567
        			fModel.elements.get(index).moveUp();
568
        			fSeparateViewer.refresh();
569
        			handleTableSelection();
570
        		}
571
        	}
572
        });
573
        fUpButton.setLayoutData(new GridData());
574
        SWTUtil.setButtonDimensionHint(fUpButton);
575
576
        fDownButton= new Button(composite, SWT.PUSH | SWT.CENTER);
577
        fDownButton.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_Down);
578
        fDownButton.addSelectionListener(new SelectionAdapter() {
579
        	@Override
580
			public void widgetSelected(SelectionEvent e) {
581
        		int index= getSelectionIndex();
582
        		if (index != -1) {
583
        			fModel.elements.get(index).moveDown();
584
        			fSeparateViewer.refresh();
585
        			handleTableSelection();
586
        		}
587
        	}
588
        });
589
        fDownButton.setLayoutData(new GridData());
590
        SWTUtil.setButtonDimensionHint(fDownButton);
591
	}
592
593
	private void createParameterTimeoutControl(Composite composite, int h_span) {
594
		Composite timeoutComposite= new Composite(composite, SWT.NONE);
595
		GridLayout layout= new GridLayout(4, false);
596
		layout.marginWidth= 0;
597
		layout.marginHeight= 0;
598
		timeoutComposite.setLayout(layout);
599
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
600
		timeoutComposite.setLayoutData(gd);
601
602
		PixelConverter pixelConverter= new PixelConverter(composite);
603
		String str= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout;
604
		addTextField(timeoutComposite, str, PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, 0, pixelConverter.convertWidthInCharsToPixels(7));
605
606
	}
607
608
	private void handleTableSelection() {
609
		ModelElement item= getSelectedItem();
610
		if (item != null) {
611
			int index= getSelectionIndex();
612
			fUpButton.setEnabled(index > 0);
613
			fDownButton.setEnabled(index < fModel.elements.size() - 1);
614
		} else {
615
			fUpButton.setEnabled(false);
616
			fDownButton.setEnabled(false);
617
		}
618
	}
619
620
	private ModelElement getSelectedItem() {
621
		return (ModelElement) ((IStructuredSelection) fSeparateViewer.getSelection()).getFirstElement();
622
	}
623
624
	private int getSelectionIndex() {
625
		return fSeparateViewer.getTable().getSelectionIndex();
626
	}
627
628
	/*
629
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
630
	 */
631
	@Override
632
	protected void updateControls() {
633
		super.updateControls();
634
635
		fModel.update();
636
		updateCheckedState();
637
		fDefaultViewer.refresh();
638
		fSeparateViewer.refresh();
639
		handleTableSelection();
640
	}
641
642
	private void updateCheckedState() {
643
		final int size= fModel.elements.size();
644
		List<ModelElement> defaultChecked= new ArrayList<ModelElement>(size);
645
		List<ModelElement> separateChecked= new ArrayList<ModelElement>(size);
646
647
		for (Iterator<ModelElement> it= fModel.elements.iterator(); it.hasNext();) {
648
			ModelElement element= it.next();
649
			if (element.isInDefaultCategory())
650
				defaultChecked.add(element);
651
			if (element.isSeparateCommand())
652
				separateChecked.add(element);
653
		}
654
655
		fDefaultViewer.setCheckedElements(defaultChecked.toArray(new Object[defaultChecked.size()]));
656
		fSeparateViewer.setCheckedElements(separateChecked.toArray(new Object[separateChecked.size()]));
657
	}
658
659
	/*
660
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer)
661
	 */
662
	@Override
663
	protected boolean processChanges(IWorkbenchPreferenceContainer container) {
664
		for (Iterator<ModelElement> it= fModel.elements.iterator(); it.hasNext();) {
665
			ModelElement item= it.next();
666
			item.update();
667
		}
668
669
		return super.processChanges(container);
670
	}
671
672
	/*
673
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String)
674
	 */
675
	@Override
676
	protected void validateSettings(Key changedKey, String oldValue, String newValue) {
677
		if (changedKey == PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC) {
678
			final StatusInfo status= new StatusInfo();
679
			if (newValue.length() == 0)
680
				status.setError(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput);
681
			else {
682
				try {
683
					int number= Integer.parseInt(newValue);
684
					int min= 0;
685
					int max= 5000;
686
					if (number < min || number > max) {
687
						String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidRange;
688
						String msg= Messages.format(msgFormat, new Object[] {new Integer(min), new Integer(max)});
689
						status.setError(msg);
690
					}
691
				} catch (NumberFormatException ex) {
692
					String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput;
693
					String msg= Messages.format(msgFormat, newValue);
694
					status.setError(msg);
695
				}
696
			}
697
			fContext.statusChanged(status);
698
		}
699
	}
700
701
	/*
702
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
703
	 */
704
	@Override
705
	protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
706
		// no builds triggered by our settings
707
		return null;
708
	}
709
710
	/*
711
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#dispose()
712
	 */
713
	@Override
714
	public void dispose() {
715
		for (Iterator<Image> it= fImages.values().iterator(); it.hasNext();) {
716
			Image image= it.next();
717
			image.dispose();
718
		}
719
720
		super.dispose();
721
	}
722
723
	private int computeWidth(Control control, String name) {
724
		if (name == null)
725
			return 0;
726
		GC gc= new GC(control);
727
		try {
728
			gc.setFont(JFaceResources.getDialogFont());
729
			return gc.stringExtent(name).x + 10;
730
		} finally {
731
			gc.dispose();
732
		}
733
	}
734
735
	private static BindingManager fgLocalBindingManager;
736
	static {
737
		fgLocalBindingManager= new BindingManager(new ContextManager(), new CommandManager());
738
		final IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getService(IBindingService.class);
739
		final Scheme[] definedSchemes= bindingService.getDefinedSchemes();
740
		if (definedSchemes != null) {
741
			try {
742
				for (int i = 0; i < definedSchemes.length; i++) {
743
					final Scheme scheme= definedSchemes[i];
744
					final Scheme copy= fgLocalBindingManager.getScheme(scheme.getId());
745
					copy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId());
746
				}
747
			} catch (final NotDefinedException e) {
748
				JavaPlugin.log(e);
749
			}
750
		}
751
		fgLocalBindingManager.setLocale(bindingService.getLocale());
752
		fgLocalBindingManager.setPlatform(bindingService.getPlatform());
753
	}
754
755
	private static String getKeyboardShortcut(ParameterizedCommand command) {
756
		IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
757
		fgLocalBindingManager.setBindings(bindingService.getBindings());
758
		try {
759
			Scheme activeScheme= bindingService.getActiveScheme();
760
			if (activeScheme != null)
761
				fgLocalBindingManager.setActiveScheme(activeScheme);
762
		} catch (NotDefinedException e) {
763
			JavaPlugin.log(e);
764
		}
765
766
		TriggerSequence[] bindings= fgLocalBindingManager.getActiveBindingsDisregardingContextFor(command);
767
		if (bindings.length > 0)
768
			return bindings[0].format();
769
		return null;
770
	}
771
772
	private Image getImage(ImageDescriptor imgDesc) {
773
		if (imgDesc == null)
774
			return null;
775
776
		Image img= fImages.get(imgDesc);
777
		if (img == null) {
778
			img= imgDesc.createImage(false);
779
			fImages.put(imgDesc, img);
780
		}
781
		return img;
782
	}
783
784
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/CodeAssistAdvancedPreferencePage.java (+2 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.preferences;
12
package org.eclipse.jdt.internal.ui.preferences;
12
13
Lines 19-24 Link Here
19
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
20
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
20
21
21
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
22
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
23
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedConfigurationBlock;
22
24
23
public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferencePage  {
25
public final class CodeAssistAdvancedPreferencePage extends PropertyAndPreferencePage  {
24
26
(-)ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java (-7 / +5 lines)
Lines 11-16 Link Here
11
 *     Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurences Pref Page; Link to
11
 *     Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurences Pref Page; Link to
12
 *     Benjamin Muskalla <b.muskalla@gmx.net> - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240
12
 *     Benjamin Muskalla <b.muskalla@gmx.net> - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240
13
 *     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
13
 *     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
14
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.ui.preferences;
16
package org.eclipse.jdt.internal.ui.preferences;
16
17
Lines 41-56 Link Here
41
	public static String ClasspathVariablesPreferencePage_savechanges_message;
42
	public static String ClasspathVariablesPreferencePage_savechanges_message;
42
	public static String CleanUpPreferencePage_Description;
43
	public static String CleanUpPreferencePage_Description;
43
	public static String CleanUpPreferencePage_Title;
44
	public static String CleanUpPreferencePage_Title;
44
	public static String CodeAssistAdvancedConfigurationBlock_default_table_category_column_title;
45
	public static String CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title;
45
	public static String CodeAssistAdvancedConfigurationBlock_default_table_description;
46
	public static String CodeAssistAdvancedConfigurationBlock_provided_table_description;
46
	public static String CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title;
47
	public static String CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title;
47
	public static String CodeAssistAdvancedConfigurationBlock_key_binding_hint;
48
	public static String CodeAssistAdvancedConfigurationBlock_key_binding_hint;
49
	public static String CodeAssistAdvancedConfigurationBlock_proposal_list_table_title;
48
	public static String CodeAssistAdvancedConfigurationBlock_page_description;
50
	public static String CodeAssistAdvancedConfigurationBlock_page_description;
49
	public static String CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title;
50
	public static String CodeAssistAdvancedConfigurationBlock_separate_table_description;
51
	public static String CodeAssistAdvancedConfigurationBlock_no_shortcut;
51
	public static String CodeAssistAdvancedConfigurationBlock_no_shortcut;
52
	public static String CodeAssistAdvancedConfigurationBlock_Up;
53
	public static String CodeAssistAdvancedConfigurationBlock_Down;
54
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout;
52
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout;
55
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput;
53
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput;
56
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput;
54
	public static String CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput;
(-)ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties (-7 / +5 lines)
Lines 11-16 Link Here
11
#     Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurrences Pref Page; Link to
11
#     Sebastian Davids, sdavids@gmx.de - 187316 [preferences] Mark Occurrences Pref Page; Link to
12
#     Benjamin Muskalla <b.muskalla@gmx.net> - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240
12
#     Benjamin Muskalla <b.muskalla@gmx.net> - [preferences] Add preference for new compiler warning: MissingSynchronizedModifierInInheritedMethod - https://bugs.eclipse.org/bugs/show_bug.cgi?id=245240
13
#     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
13
#     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
14
#     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
14
###############################################################################
15
###############################################################################
15
16
16
BuildPathsPropertyPage_error_message=An error occurred while setting the build path.
17
BuildPathsPropertyPage_error_message=An error occurred while setting the build path.
Lines 848-862 Link Here
848
CodeAssistAdvancedConfigurationBlock_page_description=Configure the behavior of the content assist ({0}) command.
849
CodeAssistAdvancedConfigurationBlock_page_description=Configure the behavior of the content assist ({0}) command.
849
# stand-in text if there is no keyboard shortcut in above statement
850
# stand-in text if there is no keyboard shortcut in above statement
850
CodeAssistAdvancedConfigurationBlock_no_shortcut=no shortcut
851
CodeAssistAdvancedConfigurationBlock_no_shortcut=no shortcut
851
CodeAssistAdvancedConfigurationBlock_default_table_description=&Select the proposal kinds contained in the 'default' content assist list:
852
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.
852
CodeAssistAdvancedConfigurationBlock_default_table_category_column_title=Default Proposal Kinds
853
CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title=Proposal Kinds
853
CodeAssistAdvancedConfigurationBlock_default_table_keybinding_column_title=Key Binding
854
CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title=Key Binding
854
# do not translate the href argument (org.eclipse.ui.preferencePages.Keys)
855
# do not translate the href argument (org.eclipse.ui.preferencePages.Keys)
855
CodeAssistAdvancedConfigurationBlock_key_binding_hint=Individual key bindings can be assigned to each proposal kind on the <a href="org.eclipse.ui.preferencePages.Keys">'Keys'</a> preference page.
856
CodeAssistAdvancedConfigurationBlock_key_binding_hint=Individual key bindings can be assigned to each proposal kind on the <a href="org.eclipse.ui.preferencePages.Keys">'Keys'</a> preference page.
856
CodeAssistAdvancedConfigurationBlock_separate_table_description=&Content assist cycling: Select the proposal kinds that are cycled through when repeatedly invoking content assist:
857
CodeAssistAdvancedConfigurationBlock_proposal_list_table_title={0}. Proposal List
857
CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title=Separate Proposal Kinds
858
CodeAssistAdvancedConfigurationBlock_Up=&Up
859
CodeAssistAdvancedConfigurationBlock_Down=D&own
860
CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout=&Timeout for fetching a parameter name from attached Javadoc (ms):
858
CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout=&Timeout for fetching a parameter name from attached Javadoc (ms):
861
859
862
CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput=Empty input.
860
CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput=Empty input.
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedConfigurationBlock.java (+459 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
11
 *******************************************************************************/
12
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced;
13
14
import java.util.HashMap;
15
import java.util.Iterator;
16
import java.util.Map;
17
18
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.dnd.Transfer;
20
import org.eclipse.swt.events.SelectionAdapter;
21
import org.eclipse.swt.events.SelectionEvent;
22
import org.eclipse.swt.graphics.GC;
23
import org.eclipse.swt.graphics.Image;
24
import org.eclipse.swt.layout.GridData;
25
import org.eclipse.swt.layout.GridLayout;
26
import org.eclipse.swt.widgets.Composite;
27
import org.eclipse.swt.widgets.Control;
28
import org.eclipse.swt.widgets.Label;
29
import org.eclipse.swt.widgets.Link;
30
import org.eclipse.swt.widgets.Table;
31
import org.eclipse.swt.widgets.TableColumn;
32
33
import org.eclipse.core.commands.Command;
34
import org.eclipse.core.commands.CommandManager;
35
import org.eclipse.core.commands.ParameterizedCommand;
36
import org.eclipse.core.commands.common.NotDefinedException;
37
import org.eclipse.core.commands.contexts.ContextManager;
38
39
import org.eclipse.core.runtime.Assert;
40
41
import org.eclipse.jface.bindings.BindingManager;
42
import org.eclipse.jface.bindings.Scheme;
43
import org.eclipse.jface.bindings.TriggerSequence;
44
import org.eclipse.jface.layout.PixelConverter;
45
import org.eclipse.jface.resource.ImageDescriptor;
46
import org.eclipse.jface.resource.JFaceResources;
47
import org.eclipse.jface.viewers.ArrayContentProvider;
48
import org.eclipse.jface.viewers.ITableLabelProvider;
49
import org.eclipse.jface.viewers.LabelProvider;
50
import org.eclipse.jface.viewers.TableViewer;
51
52
import org.eclipse.ui.PlatformUI;
53
import org.eclipse.ui.commands.ICommandService;
54
import org.eclipse.ui.dialogs.PreferencesUtil;
55
import org.eclipse.ui.keys.IBindingService;
56
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
57
58
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
59
60
import org.eclipse.jdt.core.JavaCore;
61
62
import org.eclipse.jdt.internal.corext.util.Messages;
63
64
import org.eclipse.jdt.ui.PreferenceConstants;
65
66
import org.eclipse.jdt.internal.ui.JavaPlugin;
67
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
68
import org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock;
69
import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages;
70
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProvidedCategoryListener;
71
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropIntoProvidedListener;
72
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer;
73
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
74
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer;
75
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer;
76
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement;
77
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
78
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalListSection;
79
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry;
80
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
81
82
83
/**
84
 * 
85
 * @since 3.2
86
 */
87
public final class CodeAssistAdvancedConfigurationBlock extends OptionsConfigurationBlock {
88
89
	protected static final Key PREF_PROPOSAL_LISTS= getJDTUIKey(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS);
90
91
	private static final Key PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC= getJDTCoreKey(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC);
92
93
	private static Key[] getAllKeys() {
94
		return new Key[] {
95
				PREF_PROPOSAL_LISTS,
96
				PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
97
		};
98
	}
99
100
	private static final int NUMBER_OF_PAGE_COLUMNS= 2;
101
102
	private final class ProvidedTableLabelProvider extends LabelProvider implements ITableLabelProvider {
103
104
		/*
105
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
106
		 */
107
		public Image getColumnImage(Object element, int columnIndex) {
108
			if (columnIndex == 0)
109
				return ((ModelElement) element).getImage();
110
			return null;
111
		}
112
113
		/*
114
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
115
		 */
116
		public String getColumnText(Object element, int columnIndex) {
117
			switch (columnIndex) {
118
				case 0:
119
					return ((ModelElement) element).getName();
120
				case 1:
121
					return ((ModelElement) element).getKeybindingAsString();
122
				default:
123
					Assert.isTrue(false);
124
					return null;
125
			}
126
		}
127
	}
128
129
	private final PreferenceModel fModel;
130
131
	private final Map<ImageDescriptor, Image> fImages= new HashMap<ImageDescriptor, Image>();
132
133
	private TableViewer fProvidedViewer;
134
135
	private ProposalListSection fProposalListSection;
136
137
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
138
139
	public CodeAssistAdvancedConfigurationBlock(IStatusChangeListener statusListener, IWorkbenchPreferenceContainer container) {
140
		super(statusListener, null, getAllKeys(), container);
141
		fUtilitiesProxy= new CodeAssistAdvancedUtilitiesProxy(this);
142
		fModel= new PreferenceModel(CompletionProposalComputerRegistry.getDefault(), fUtilitiesProxy);
143
	}
144
145
	/*
146
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#createContents(org.eclipse.swt.widgets.Composite)
147
	 */
148
	@Override
149
	public Control createContents(Composite parent) {
150
		Composite composite= createWrappingComposite(parent);
151
152
		createPageDescription(composite);
153
154
		createProvidedSection(composite);
155
		fProposalListSection= new ProposalListSection(composite, fModel, fUtilitiesProxy);
156
157
		createFiller(composite);
158
159
		createParameterTimeoutControl(composite);
160
161
		updateControls();
162
		selectFirstProvidedCategory();
163
164
		return composite;
165
	}
166
167
	private Composite createWrappingComposite(Composite parent) {
168
		Composite composite= new Composite(parent, SWT.NONE);
169
		GridLayout layout= new GridLayout(NUMBER_OF_PAGE_COLUMNS, false);
170
		layout.marginWidth= 0;
171
		layout.marginHeight= 0;
172
		composite.setLayout(layout);
173
		return composite;
174
	}
175
176
	private void createPageDescription(Composite composite) {
177
		final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
178
		final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
179
		ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
180
		String key= getKeyboardShortcut(pCmd);
181
		if (key == null)
182
			key= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_no_shortcut;
183
184
		PixelConverter pixelConverter= new PixelConverter(composite);
185
		int width= pixelConverter.convertWidthInCharsToPixels(40);
186
187
		Label label= new Label(composite, SWT.NONE | SWT.WRAP);
188
		label.setText(Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_page_description, new Object[] { key }));
189
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, NUMBER_OF_PAGE_COLUMNS, 1);
190
		gd.widthHint= width;
191
		label.setLayoutData(gd);
192
	}
193
194
	private void createProvidedSection(Composite composite) {
195
		Composite providedContainer= new Composite(composite, SWT.NONE);
196
		GridLayout layout= new GridLayout();
197
		layout.marginWidth= 0;
198
		layout.marginHeight= 0;
199
		providedContainer.setLayout(layout);
200
		providedContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
201
202
		createProvidedViewer(providedContainer);
203
		createProvidedLabel(providedContainer);
204
		createKeysLink(providedContainer);
205
	}
206
207
	private void createProvidedViewer(Composite composite) {
208
		fProvidedViewer= new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);
209
		Table table= fProvidedViewer.getTable();
210
		table.setHeaderVisible(true);
211
		table.setLinesVisible(false);
212
		GridData gridData= new GridData(SWT.FILL, SWT.FILL, true, true);
213
		gridData.heightHint= 0;
214
		table.setLayoutData(gridData);
215
216
		TableColumn nameColumn= new TableColumn(table, SWT.NONE);
217
		nameColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_category_column_title);
218
		nameColumn.setResizable(false);
219
		TableColumn keyColumn= new TableColumn(table, SWT.NONE);
220
		keyColumn.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_keybinding_column_title);
221
		keyColumn.setResizable(false);
222
223
		fProvidedViewer.setContentProvider(new ArrayContentProvider());
224
		ProvidedTableLabelProvider labelProvider= new ProvidedTableLabelProvider();
225
		fProvidedViewer.setLabelProvider(labelProvider);
226
		fProvidedViewer.setInput(fModel.elements);
227
		fProvidedViewer.setComparator(new ModelElement.ModelElementViewerComparator()); // sort alphabetically
228
229
		final int ICON_WIDTH= 16;
230
		final int HEADER_MARGIN= 20;
231
		int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
232
		int minKeyWidth= computeWidth(table, keyColumn.getText()) + HEADER_MARGIN;
233
		for (int i= 0; i < fModel.elements.size(); i++) {
234
			minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 0)) + ICON_WIDTH);
235
			minKeyWidth= Math.max(minKeyWidth, computeWidth(table, labelProvider.getColumnText(fModel.elements.get(i), 1)));
236
		}
237
		nameColumn.setWidth(minNameWidth);
238
		keyColumn.setWidth(minKeyWidth);
239
240
		// add drag support for provided categories
241
		Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance() };
242
		fProvidedViewer.addDragSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, new DragProvidedCategoryListener(fProvidedViewer));
243
244
		// add drop support for proposal lists and proposal list categories
245
		transferTypes= new Transfer[] { ProposalListTransfer.getInstance(), ProposalListCategoryTransfer.getInstance() };
246
		fProvidedViewer.addDropSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, new DropIntoProvidedListener(fProvidedViewer, fModel, fUtilitiesProxy));
247
	}
248
249
	private void createProvidedLabel(Composite composite) {
250
		PixelConverter pixelConverter= new PixelConverter(composite);
251
		int width= pixelConverter.convertWidthInCharsToPixels(40);
252
253
		Label label= new Label(composite, SWT.NONE | SWT.WRAP);
254
		label.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_provided_table_description);
255
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false);
256
		gd.widthHint= width;
257
		label.setLayoutData(gd);
258
	}
259
260
	private void createKeysLink(Composite composite) {
261
		Link link= new Link(composite, SWT.NONE | SWT.WRAP);
262
		link.setText(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_key_binding_hint);
263
		link.addSelectionListener(new SelectionAdapter() {
264
			@Override
265
			public void widgetSelected(SelectionEvent e) {
266
				PreferencesUtil.createPreferenceDialogOn(getShell(), e.text, null, null);
267
			}
268
		});
269
270
		PixelConverter pixelConverter= new PixelConverter(composite);
271
		int width= pixelConverter.convertWidthInCharsToPixels(40);
272
273
		// limit the size of the Link as it would take all it can get
274
		GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false);
275
		gd.widthHint= width;
276
		link.setLayoutData(gd);
277
	}
278
279
	private void createFiller(Composite composite) {
280
		Label filler= new Label(composite, SWT.NONE);
281
		filler.setVisible(false);
282
		filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, NUMBER_OF_PAGE_COLUMNS, 1));
283
	}
284
285
	private void createParameterTimeoutControl(Composite composite) {
286
		Composite timeoutComposite= new Composite(composite, SWT.NONE);
287
		GridLayout layout= new GridLayout(4, false);
288
		layout.marginWidth= 0;
289
		layout.marginHeight= 0;
290
		timeoutComposite.setLayout(layout);
291
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, NUMBER_OF_PAGE_COLUMNS, 1);
292
		timeoutComposite.setLayoutData(gd);
293
294
		PixelConverter pixelConverter= new PixelConverter(composite);
295
		String str= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout;
296
		addTextField(timeoutComposite, str, PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, 0, pixelConverter.convertWidthInCharsToPixels(7));
297
	}
298
299
	private void selectFirstProvidedCategory() {
300
		if (fModel.elements.size() > 0) {
301
			fProvidedViewer.getTable().select(0);
302
		}
303
	}
304
305
	/*
306
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#settingsUpdated()
307
	 */
308
	@Override
309
	protected void settingsUpdated() {
310
		if (fModel != null)
311
			fModel.updatePreferenceModel();
312
	}
313
314
	/*
315
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#updateControls()
316
	 */
317
	@Override
318
	protected void updateControls() {
319
		super.updateControls();
320
		fProvidedViewer.refresh();
321
		fProposalListSection.updateControls();
322
	}
323
324
	/*
325
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#processChanges(org.eclipse.ui.preferences.IWorkbenchPreferenceContainer)
326
	 */
327
	@Override
328
	protected boolean processChanges(IWorkbenchPreferenceContainer container) {
329
		fModel.updatePreferenceModel();
330
		return super.processChanges(container);
331
	}
332
333
	/*
334
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#setValue(Key, String)
335
	 */
336
	@Override
337
	protected String setValue(Key key, String value) {
338
		return super.setValue(key, value);
339
	}
340
341
	/*
342
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getValue(Key)
343
	 */
344
	@Override
345
	protected String getValue(Key key) {
346
		return super.getValue(key);
347
	}
348
349
	/*
350
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#validateSettings(org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock.Key, java.lang.String, java.lang.String)
351
	 */
352
	@Override
353
	protected void validateSettings(Key changedKey, String oldValue, String newValue) {
354
		if (changedKey == PREF_CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC) {
355
			final StatusInfo status= new StatusInfo();
356
			if (newValue.length() == 0)
357
				status.setError(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_emptyInput);
358
			else {
359
				try {
360
					int number= Integer.parseInt(newValue);
361
					int min= 0;
362
					int max= 5000;
363
					if (number < min || number > max) {
364
						String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidRange;
365
						String msg= Messages.format(msgFormat, new Object[] { new Integer(min), new Integer(max) });
366
						status.setError(msg);
367
					}
368
				} catch (NumberFormatException ex) {
369
					String msgFormat= PreferencesMessages.CodeAssistAdvancedConfigurationBlock_parameterNameFromAttachedJavadoc_timeout_invalidInput;
370
					String msg= Messages.format(msgFormat, newValue);
371
					status.setError(msg);
372
				}
373
			}
374
			fContext.statusChanged(status);
375
		}
376
	}
377
378
	/*
379
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#getFullBuildDialogStrings(boolean)
380
	 */
381
	@Override
382
	protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
383
		// no builds triggered by our settings
384
		return null;
385
	}
386
387
	/*
388
	 * @see org.eclipse.jdt.internal.ui.preferences.OptionsConfigurationBlock#dispose()
389
	 */
390
	@Override
391
	public void dispose() {
392
		for (Iterator<Image> it= fImages.values().iterator(); it.hasNext();) {
393
			Image image= it.next();
394
			image.dispose();
395
		}
396
		super.dispose();
397
	}
398
399
	protected int computeWidth(Control control, String name) {
400
		if (name == null)
401
			return 0;
402
		GC gc= new GC(control);
403
		try {
404
			gc.setFont(JFaceResources.getDialogFont());
405
			return gc.stringExtent(name).x + 10;
406
		} finally {
407
			gc.dispose();
408
		}
409
	}
410
411
	protected Image getImage(ImageDescriptor imgDesc) {
412
		if (imgDesc == null)
413
			return null;
414
415
		Image img= fImages.get(imgDesc);
416
		if (img == null) {
417
			img= imgDesc.createImage(false);
418
			fImages.put(imgDesc, img);
419
		}
420
		return img;
421
	}
422
423
	private static BindingManager fgLocalBindingManager;
424
	static {
425
		fgLocalBindingManager= new BindingManager(new ContextManager(), new CommandManager());
426
		final IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class);
427
		final Scheme[] definedSchemes= bindingService.getDefinedSchemes();
428
		if (definedSchemes != null) {
429
			try {
430
				for (int i= 0; i < definedSchemes.length; i++) {
431
					final Scheme scheme= definedSchemes[i];
432
					final Scheme copy= fgLocalBindingManager.getScheme(scheme.getId());
433
					copy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId());
434
				}
435
			} catch (final NotDefinedException e) {
436
				JavaPlugin.log(e);
437
			}
438
		}
439
		fgLocalBindingManager.setLocale(bindingService.getLocale());
440
		fgLocalBindingManager.setPlatform(bindingService.getPlatform());
441
	}
442
443
	protected static String getKeyboardShortcut(ParameterizedCommand command) {
444
		IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
445
		fgLocalBindingManager.setBindings(bindingService.getBindings());
446
		try {
447
			Scheme activeScheme= bindingService.getActiveScheme();
448
			if (activeScheme != null)
449
				fgLocalBindingManager.setActiveScheme(activeScheme);
450
		} catch (NotDefinedException e) {
451
			JavaPlugin.log(e);
452
		}
453
454
		TriggerSequence[] bindings= fgLocalBindingManager.getActiveBindingsDisregardingContextFor(command);
455
		if (bindings.length > 0)
456
			return bindings[0].format();
457
		return null;
458
	}
459
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/CodeAssistAdvancedUtilitiesProxy.java (+103 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced;
12
13
import org.eclipse.swt.SWT;
14
import org.eclipse.swt.dnd.DND;
15
import org.eclipse.swt.dnd.TransferData;
16
import org.eclipse.swt.graphics.Color;
17
import org.eclipse.swt.graphics.Image;
18
import org.eclipse.swt.widgets.Control;
19
import org.eclipse.swt.widgets.Display;
20
21
import org.eclipse.core.commands.ParameterizedCommand;
22
23
import org.eclipse.jface.resource.ImageDescriptor;
24
25
import org.eclipse.ui.plugin.AbstractUIPlugin;
26
27
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer;
28
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
29
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer;
30
31
/**
32
 * 
33
 * @since 3.8
34
 */
35
public class CodeAssistAdvancedUtilitiesProxy {
36
	public static final Color SELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION);
37
38
	public static final Color SELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
39
40
	public static final Color UNSELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
41
42
	public static final Color UNSELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
43
44
	public static final Color UNSELECTED_BORDER_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
45
46
	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$
47
48
	private static final ImageDescriptor REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR= AbstractUIPlugin.imageDescriptorFromPlugin(
49
			"org.eclipse.jdt.ui", "$nl$/icons/full/elcl16/remove_proposal_list_over.gif"); //$NON-NLS-1$ //$NON-NLS-2$
50
51
	private CodeAssistAdvancedConfigurationBlock fConfigurationBlock;
52
53
	public final Image fRemoveProposalListImage;
54
55
	public final Image fRemoveProposalListOverImage;
56
57
	public CodeAssistAdvancedUtilitiesProxy(CodeAssistAdvancedConfigurationBlock configurationBlock) {
58
		this.fConfigurationBlock= configurationBlock;
59
		fRemoveProposalListImage= getImage(REMOVE_PROPOSAL_LIST_ICON_DESCRIPTOR);
60
		fRemoveProposalListOverImage= getImage(REMOVE_PROPOSAL_LIST_OVER_ICON_DESCRIPTOR);
61
	}
62
63
	public void updateControls() {
64
		fConfigurationBlock.updateControls();
65
	}
66
67
	public int computeWidth(Control control, String name) {
68
		return fConfigurationBlock.computeWidth(control, name);
69
	}
70
71
	public Image getImage(ImageDescriptor imgDesc) {
72
		return fConfigurationBlock.getImage(imgDesc);
73
	}
74
75
	public String getKeyboardShortcut(ParameterizedCommand command) {
76
		return CodeAssistAdvancedConfigurationBlock.getKeyboardShortcut(command);
77
	}
78
79
	public String setValue(String value) {
80
		return fConfigurationBlock.setValue(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS, value);
81
	}
82
83
	public String getValue() {
84
		return fConfigurationBlock.getValue(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS);
85
	}
86
87
	public void validateSettings(String oldValue, String newValue) {
88
		fConfigurationBlock.validateSettings(CodeAssistAdvancedConfigurationBlock.PREF_PROPOSAL_LISTS, oldValue, newValue);
89
	}
90
91
	public static int getCompatibleOperation(int operation, int supportedOperations, TransferData currentDataType) {
92
		int result= ProvidedCategoryTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType);
93
		if (result != -1)
94
			return result;
95
		result= ProposalListTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType);
96
		if (result != -1)
97
			return result;
98
		result= ProposalListCategoryTransfer.getInstance().getCompatibleOperation(operation, supportedOperations, currentDataType);
99
		if (result != -1)
100
			return result;
101
		return DND.DROP_NONE;
102
	}
103
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/AutoscrollDropTargetListener.java (+52 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
import org.eclipse.swt.dnd.DropTargetEvent;
15
import org.eclipse.swt.dnd.DropTargetListener;
16
17
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalListSection;
18
19
/**
20
 * 
21
 * @since 3.8
22
 */
23
public final class AutoscrollDropTargetListener implements DropTargetListener {
24
	private ProposalListSection fProposalListSection;
25
26
	public AutoscrollDropTargetListener(ProposalListSection proposalListSection) {
27
		this.fProposalListSection= proposalListSection;
28
	}
29
30
	public void dragEnter(DropTargetEvent event) {
31
		event.detail= DND.DROP_NONE;
32
	}
33
34
	public void dragLeave(DropTargetEvent event) {
35
	}
36
37
	public void dragOperationChanged(DropTargetEvent event) {
38
		event.detail= DND.DROP_NONE;
39
	}
40
41
	public void dragOver(DropTargetEvent event) {
42
		fProposalListSection.autoScroll(event);
43
	}
44
45
	public void drop(DropTargetEvent event) {
46
		event.detail= DND.DROP_NONE;
47
	}
48
49
	public void dropAccept(DropTargetEvent event) {
50
		event.detail= DND.DROP_NONE;
51
	}
52
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListCategoryListener.java (+54 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DragSourceEvent;
14
import org.eclipse.swt.dnd.DragSourceListener;
15
16
import org.eclipse.jface.viewers.IStructuredSelection;
17
import org.eclipse.jface.viewers.TableViewer;
18
19
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement;
20
21
/**
22
 * 
23
 * @since 3.8
24
 */
25
public final class DragProposalListCategoryListener implements DragSourceListener {
26
	private final TableViewer fViewer;
27
28
	private final Integer fListIndex;
29
30
	public DragProposalListCategoryListener(TableViewer viewer, int listIndex) {
31
		this.fViewer= viewer;
32
		this.fListIndex= Integer.valueOf(listIndex);
33
	}
34
35
	public void dragSetData(DragSourceEvent event) {
36
		if (ProposalListCategoryTransfer.getInstance().isSupportedType(event.dataType)) {
37
			IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection();
38
			if (fViewer.getSelection() != null && !fViewer.getSelection().isEmpty()) {
39
				ModelElement firstElement= (ModelElement) selection.getFirstElement();
40
				if (firstElement != null)
41
					event.data= new ProposalTransferType[] { new ProposalTransferType(firstElement.getId(), fListIndex) };
42
			}
43
		}
44
	}
45
46
	public void dragStart(DragSourceEvent event) {
47
		if (fViewer.getSelection() == null || fViewer.getSelection().isEmpty() || ((IStructuredSelection) fViewer.getSelection()).getFirstElement() == null) {
48
			event.doit= false;
49
		}
50
	}
51
52
	public void dragFinished(DragSourceEvent event) {
53
	}
54
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProposalListListener.java (+38 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DragSourceEvent;
14
import org.eclipse.swt.dnd.DragSourceListener;
15
16
/**
17
 * 
18
 * @since 3.8
19
 */
20
public final class DragProposalListListener implements DragSourceListener {
21
	private final Integer fListIndex;
22
23
	public DragProposalListListener(int listIndex) {
24
		this.fListIndex= Integer.valueOf(listIndex);
25
	}
26
27
	public void dragSetData(DragSourceEvent event) {
28
		if (ProposalListTransfer.getInstance().isSupportedType(event.dataType)) {
29
			event.data= new ProposalTransferType[] { new ProposalTransferType(fListIndex) };
30
		}
31
	}
32
33
	public void dragStart(DragSourceEvent event) {
34
	}
35
36
	public void dragFinished(DragSourceEvent event) {
37
	}
38
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DragProvidedCategoryListener.java (+51 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DragSourceEvent;
14
import org.eclipse.swt.dnd.DragSourceListener;
15
16
import org.eclipse.jface.viewers.IStructuredSelection;
17
import org.eclipse.jface.viewers.TableViewer;
18
19
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement;
20
21
/**
22
 * 
23
 * @since 3.8
24
 */
25
public final class DragProvidedCategoryListener implements DragSourceListener {
26
	private final TableViewer fViewer;
27
28
	public DragProvidedCategoryListener(TableViewer viewer) {
29
		this.fViewer= viewer;
30
	}
31
32
	public void dragSetData(DragSourceEvent event) {
33
		if (ProvidedCategoryTransfer.getInstance().isSupportedType(event.dataType)) {
34
			IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection();
35
			if (fViewer.getSelection() != null && !fViewer.getSelection().isEmpty()) {
36
				ModelElement firstElement= (ModelElement) selection.getFirstElement();
37
				if (firstElement != null)
38
					event.data= new ProposalTransferType[] { new ProposalTransferType(firstElement.getId()) };
39
			}
40
		}
41
	}
42
43
	public void dragStart(DragSourceEvent event) {
44
		if (fViewer.getSelection() == null || fViewer.getSelection().isEmpty() || ((IStructuredSelection) fViewer.getSelection()).getFirstElement() == null) {
45
			event.doit= false;
46
		}
47
	}
48
49
	public void dragFinished(DragSourceEvent event) {
50
	}
51
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProposalListListener.java (+144 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
import org.eclipse.swt.dnd.DropTargetEvent;
15
import org.eclipse.swt.dnd.TransferData;
16
17
import org.eclipse.jface.viewers.ViewerDropAdapter;
18
19
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
20
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
21
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalList;
22
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalListSection;
23
24
/**
25
 * 
26
 * @since 3.8
27
 */
28
public final class DropIntoProposalListListener extends ViewerDropAdapter {
29
	private final PreferenceModel fModel;
30
31
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
32
33
	private final int fListIndex;
34
35
	private final ProposalListSection fProposalListSection;
36
37
	private final ProposalList fProposalList;
38
39
	public DropIntoProposalListListener(ProposalList proposalList, int listIndex, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy, ProposalListSection proposalListSection) {
40
		super(proposalList.getTableViewer());
41
		this.fListIndex= listIndex;
42
		this.fProposalList= proposalList;
43
		this.fModel= model;
44
		this.fUtilitiesProxy= utilitiesProxy;
45
		this.fProposalListSection= proposalListSection;
46
	}
47
48
	@Override
49
	public void dragEnter(DropTargetEvent event) {
50
		event.detail= CodeAssistAdvancedUtilitiesProxy.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
51
	}
52
53
	@Override
54
	public void drop(DropTargetEvent event) {
55
		super.drop(event);
56
		drop: {
57
			if (event.data == null)
58
				break drop;
59
			ProposalTransferType data= ((ProposalTransferType[]) event.data)[0];
60
			if (data.getListIndex() == null && fModel.isValidCategoryId(data.getCategoryId())) {
61
				// category dragged from provided list
62
				switch (event.detail) {
63
					case DND.DROP_COPY:
64
						fModel.getElement(data.getCategoryId()).setInProposalList(fListIndex);
65
						break;
66
					default:
67
						break drop;
68
				}
69
				fUtilitiesProxy.updateControls();
70
				return;
71
			}
72
			if (data.getListIndex() == null)
73
				break drop;
74
			int sourceListIndex= data.getListIndex().intValue();
75
			if (sourceListIndex == fListIndex)
76
				break drop;
77
			if (data.getCategoryId() == null) {
78
				// proposal list has been dragged
79
				switch (event.detail) {
80
					case DND.DROP_COPY:
81
						// COPY all elements from source list to this list
82
						fModel.mergeLists(sourceListIndex, fListIndex, false);
83
						break;
84
					case DND.DROP_MOVE:
85
						// MOVE all elements from source list to this list
86
						fModel.mergeLists(sourceListIndex, fListIndex, true);
87
						break;
88
					default:
89
						break drop;
90
				}
91
				fUtilitiesProxy.updateControls();
92
				return;
93
			}
94
			if (fModel.isValidCategoryId(data.getCategoryId())) {
95
				// category dragged from proposal list
96
				switch (event.detail) {
97
					case DND.DROP_COPY:
98
						fModel.getElement(data.getCategoryId()).setInProposalList(fListIndex);
99
						break;
100
					case DND.DROP_MOVE:
101
						fModel.getElement(data.getCategoryId()).moveToProposalList(sourceListIndex, fListIndex);
102
						break;
103
					default:
104
						break drop;
105
				}
106
				fUtilitiesProxy.updateControls();
107
				return;
108
			}
109
		}
110
		event.detail= DND.DROP_NONE;
111
	}
112
113
	@Override
114
	public boolean performDrop(Object data) {
115
		return true; // behavior completely implemented in drop-method
116
	}
117
118
	@Override
119
	public void dragOperationChanged(DropTargetEvent event) {
120
		event.detail= CodeAssistAdvancedUtilitiesProxy.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
121
		if (event.detail == DND.DROP_NONE)
122
			fProposalList.highlight(false);
123
	}
124
125
	@Override
126
	public boolean validateDrop(Object target, int operation, TransferData transferType) {
127
		return ProvidedCategoryTransfer.getInstance().isSupportedType(transferType) ||
128
				ProposalListCategoryTransfer.getInstance().isSupportedType(transferType) ||
129
				ProposalListTransfer.getInstance().isSupportedType(transferType);
130
	}
131
132
	@Override
133
	public void dragOver(DropTargetEvent event) {
134
		event.feedback= DND.FEEDBACK_NONE;
135
		if (event.detail != DND.DROP_NONE)
136
			fProposalList.highlight(true);
137
		fProposalListSection.autoScroll(event);
138
	}
139
140
	@Override
141
	public void dragLeave(DropTargetEvent event) {
142
		fProposalList.highlight(false);
143
	}
144
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropIntoProvidedListener.java (+82 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
import org.eclipse.swt.dnd.DropTargetEvent;
15
import org.eclipse.swt.dnd.TransferData;
16
17
import org.eclipse.jface.viewers.TableViewer;
18
import org.eclipse.jface.viewers.ViewerDropAdapter;
19
20
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
21
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
22
23
/**
24
 * 
25
 * @since 3.8
26
 */
27
public final class DropIntoProvidedListener extends ViewerDropAdapter {
28
	private final PreferenceModel fModel;
29
30
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
31
32
	public DropIntoProvidedListener(TableViewer viewer, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
33
		super(viewer);
34
		this.fModel= model;
35
		this.fUtilitiesProxy= utilitiesProxy;
36
	}
37
38
	@Override
39
	public boolean validateDrop(Object target, int operation, TransferData transferType) {
40
		return ProposalListCategoryTransfer.getInstance().isSupportedType(transferType) ||
41
				ProposalListTransfer.getInstance().isSupportedType(transferType);
42
	}
43
44
	@Override
45
	public boolean performDrop(Object data) {
46
		ProposalTransferType transferData= ((ProposalTransferType[]) data)[0];
47
		if (transferData.getListIndex() != null) {
48
			int listIndex= transferData.getListIndex().intValue();
49
			if (fModel.isValidCategoryId(transferData.getCategoryId()))
50
				// category dragged from proposal list
51
				fModel.getElement(transferData.getCategoryId()).removeInProposalList(listIndex);
52
			else if (transferData.getCategoryId() == null)
53
				// proposal list has been dragged
54
				fModel.removeList(listIndex);
55
			fUtilitiesProxy.updateControls();
56
			return true;
57
		}
58
		return false;
59
	}
60
61
	@Override
62
	public void dragEnter(DropTargetEvent event) {
63
		event.detail= this.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
64
	}
65
66
	@Override
67
	public void dragOperationChanged(DropTargetEvent event) {
68
		event.detail= this.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
69
	}
70
71
	@Override
72
	public void dragOver(DropTargetEvent event) {
73
		event.feedback= DND.FEEDBACK_NONE;
74
	}
75
76
	private int getCompatibleOperation(int detail, int operations, TransferData currentDataType) {
77
		int operation= CodeAssistAdvancedUtilitiesProxy.getCompatibleOperation(detail, operations, currentDataType);
78
		if (operation != DND.DROP_MOVE)
79
			return DND.DROP_NONE;
80
		return operation;
81
	}
82
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/DropNewProposalListListener.java (+138 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import java.util.Arrays;
14
15
import org.eclipse.swt.dnd.DND;
16
import org.eclipse.swt.dnd.DropTargetEvent;
17
import org.eclipse.swt.dnd.DropTargetListener;
18
import org.eclipse.swt.widgets.Composite;
19
20
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
21
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
22
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets.ProposalListSection;
23
24
/**
25
 * 
26
 * @since 3.8
27
 */
28
public final class DropNewProposalListListener implements DropTargetListener {
29
30
	private final ProposalListSection fProposalListSection;
31
32
	private final Composite fHighlightComposite;
33
34
	private final int fListIndex;
35
36
	private final PreferenceModel fModel;
37
38
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
39
40
	public DropNewProposalListListener(Composite highlightComposite, int listIndex, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy, ProposalListSection proposalListSection) {
41
		this.fHighlightComposite= highlightComposite;
42
		this.fListIndex= listIndex;
43
		this.fModel= model;
44
		this.fUtilitiesProxy= utilitiesProxy;
45
		this.fProposalListSection= proposalListSection;
46
	}
47
48
	public void dragEnter(DropTargetEvent event) {
49
		event.detail= CodeAssistAdvancedUtilitiesProxy.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
50
	}
51
52
	public void dragOperationChanged(DropTargetEvent event) {
53
		event.detail= CodeAssistAdvancedUtilitiesProxy.getCompatibleOperation(event.detail, event.operations, event.currentDataType);
54
		if (event.detail == DND.DROP_NONE)
55
			highlight(false);
56
	}
57
58
	public void dragOver(DropTargetEvent event) {
59
		if (event.detail != DND.DROP_NONE) {
60
			highlight(true);
61
		}
62
		fProposalListSection.autoScroll(event);
63
	}
64
65
	public void dragLeave(DropTargetEvent event) {
66
		highlight(false);
67
	}
68
69
	private void highlight(boolean selected) {
70
		if (selected)
71
			fHighlightComposite.setBackground(CodeAssistAdvancedUtilitiesProxy.SELECTED_COLOR);
72
		else
73
			fHighlightComposite.setBackground(CodeAssistAdvancedUtilitiesProxy.UNSELECTED_COLOR);
74
		fHighlightComposite.update();
75
	}
76
77
	public void drop(DropTargetEvent event) {
78
		drop: {
79
			if (event.data == null)
80
				break drop;
81
			ProposalTransferType data= ((ProposalTransferType[]) event.data)[0];
82
			if (data.getListIndex() == null && fModel.isValidCategoryId(data.getCategoryId())) {
83
				// category dragged from provided list
84
				switch (event.detail) {
85
					case DND.DROP_COPY:
86
						fModel.addNewList(fListIndex, Arrays.asList(data.getCategoryId()));
87
						break;
88
					default:
89
						break drop;
90
				}
91
				fUtilitiesProxy.updateControls();
92
				return;
93
			}
94
			if (data.getListIndex() == null)
95
				break drop;
96
			int sourceListIndex= data.getListIndex().intValue();
97
			if (data.getCategoryId() == null) {
98
				// proposal list has been dragged
99
				switch (event.detail) {
100
					case DND.DROP_COPY:
101
						fModel.addNewList(fListIndex, fModel.getCategoryIds(sourceListIndex));
102
						break;
103
					case DND.DROP_MOVE:
104
						if (sourceListIndex != fListIndex && sourceListIndex + 1 != fListIndex)
105
							fModel.moveList(sourceListIndex, fListIndex);
106
						else
107
							break drop;
108
						break;
109
					default:
110
						break drop;
111
				}
112
				fUtilitiesProxy.updateControls();
113
				return;
114
			}
115
			if (fModel.isValidCategoryId(data.getCategoryId())) {
116
				// category dragged from proposal list
117
				switch (event.detail) {
118
					case DND.DROP_MOVE:
119
						fModel.addNewList(fListIndex, Arrays.asList(data.getCategoryId()));
120
						int removeIndex= fListIndex > sourceListIndex ? sourceListIndex : sourceListIndex + 1;
121
						fModel.getElement(data.getCategoryId()).removeInProposalList(removeIndex);
122
						break;
123
					case DND.DROP_COPY:
124
						fModel.addNewList(fListIndex, Arrays.asList(data.getCategoryId()));
125
						break;
126
					default:
127
						break drop;
128
				}
129
				fUtilitiesProxy.updateControls();
130
				return;
131
			}
132
		}
133
		event.detail= DND.DROP_NONE;
134
	}
135
136
	public void dropAccept(DropTargetEvent event) {
137
	}
138
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListCategoryTransfer.java (+45 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
15
/**
16
 * 
17
 * @since 3.8
18
 */
19
public final class ProposalListCategoryTransfer extends ProposalTransfer {
20
	private static final String TRANSFER_NAME= "ProposalListCategoryTransfer"; //$NON-NLS-1$
21
22
	private static final ProposalListCategoryTransfer instance= new ProposalListCategoryTransfer();
23
24
	private ProposalListCategoryTransfer() {
25
		super(TRANSFER_NAME);
26
	}
27
28
	public static ProposalListCategoryTransfer getInstance() {
29
		return instance;
30
	}
31
32
	@Override
33
	public int getDefaultOperation(int supportedOperations) {
34
		if ((supportedOperations & DND.DROP_MOVE) != 0)
35
			return DND.DROP_MOVE;
36
		else if ((supportedOperations & DND.DROP_COPY) != 0)
37
			return DND.DROP_COPY;
38
		return DND.DROP_NONE;
39
	}
40
41
	@Override
42
	public boolean isSupportedOperation(int operation) {
43
		return operation == DND.DROP_COPY || operation == DND.DROP_MOVE;
44
	}
45
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalListTransfer.java (+45 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
15
/**
16
 * 
17
 * @since 3.8
18
 */
19
public final class ProposalListTransfer extends ProposalTransfer {
20
	private static final String TRANSFER_NAME= "ProposalListTransfer"; //$NON-NLS-1$
21
22
	private static final ProposalListTransfer instance= new ProposalListTransfer();
23
24
	private ProposalListTransfer() {
25
		super(TRANSFER_NAME);
26
	}
27
28
	public static ProposalListTransfer getInstance() {
29
		return instance;
30
	}
31
32
	@Override
33
	public int getDefaultOperation(int supportedOperations) {
34
		if ((supportedOperations & DND.DROP_MOVE) != 0)
35
			return DND.DROP_MOVE;
36
		else if ((supportedOperations & DND.DROP_COPY) != 0)
37
			return DND.DROP_COPY;
38
		return DND.DROP_NONE;
39
	}
40
41
	@Override
42
	public boolean isSupportedOperation(int operation) {
43
		return operation == DND.DROP_COPY || operation == DND.DROP_MOVE;
44
	}
45
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransfer.java (+148 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import java.io.ByteArrayInputStream;
14
import java.io.ByteArrayOutputStream;
15
import java.io.DataInputStream;
16
import java.io.DataOutputStream;
17
import java.io.IOException;
18
import java.util.ArrayList;
19
import java.util.List;
20
21
import org.eclipse.swt.dnd.ByteArrayTransfer;
22
import org.eclipse.swt.dnd.DND;
23
import org.eclipse.swt.dnd.TransferData;
24
25
/**
26
 * 
27
 * @since 3.8
28
 */
29
public abstract class ProposalTransfer extends ByteArrayTransfer {
30
	public static final int ALL_DRAG_OPERATIONS= DND.DROP_COPY | DND.DROP_DEFAULT | DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_TARGET_MOVE;
31
32
	private final String fTransferName;
33
34
	private final int fTransferId;
35
36
	protected ProposalTransfer(String transferName) {
37
		this.fTransferName= transferName;
38
		this.fTransferId= registerType(transferName);
39
	}
40
41
	public abstract int getDefaultOperation(int supportedOperations);
42
43
	public abstract boolean isSupportedOperation(int operation);
44
45
	@Override
46
	public void javaToNative(Object object, TransferData transferData) {
47
		if (!checkProposalTransferType(object) || !isSupportedType(transferData))
48
			DND.error(DND.ERROR_INVALID_DATA);
49
		ProposalTransferType[] props= (ProposalTransferType[]) object;
50
		ByteArrayOutputStream out= new ByteArrayOutputStream();
51
		DataOutputStream writeOut= new DataOutputStream(out);
52
		try {
53
			for (int i= 0, length= props.length; i < length; i++) {
54
				if (props[i].getCategoryId() != null) {
55
					byte[] buffer= props[i].getCategoryId().getBytes();
56
					writeOut.writeInt(buffer.length);
57
					writeOut.write(buffer);
58
				} else
59
					writeOut.writeInt(0);
60
				Integer index= props[i].getListIndex();
61
				writeOut.writeInt(index == null ? -1 : index.intValue());
62
			}
63
			byte[] buffer= out.toByteArray();
64
			super.javaToNative(buffer, transferData);
65
		} catch (IOException e) {
66
		} finally {
67
			try {
68
				writeOut.close();
69
			} catch (IOException e) {
70
			}
71
		}
72
	}
73
74
	@Override
75
	public Object nativeToJava(TransferData transferData) {
76
		if (isSupportedType(transferData)) {
77
			byte[] buffer= (byte[]) super.nativeToJava(transferData);
78
			if (buffer == null)
79
				return null;
80
81
			List<ProposalTransferType> props= new ArrayList<ProposalTransferType>();
82
			ByteArrayInputStream in= new ByteArrayInputStream(buffer);
83
			DataInputStream readIn= new DataInputStream(in);
84
			try {
85
				while (readIn.available() > 0) {
86
					ProposalTransferType proposal= new ProposalTransferType();
87
					int size= readIn.readInt();
88
					if (size == 0)
89
						proposal.setCategoryId(null);
90
					else {
91
						byte[] id= new byte[size];
92
						readIn.read(id);
93
						proposal.setCategoryId(new String(id));
94
					}
95
					int index= readIn.readInt();
96
					proposal.setListIndex(index < 0 ? null : Integer.valueOf(index));
97
					props.add(proposal);
98
				}
99
			} catch (IOException ex) {
100
				return null;
101
			} finally {
102
				try {
103
					readIn.close();
104
				} catch (IOException e) {
105
					return null;
106
				}
107
			}
108
			return props.toArray(new ProposalTransferType[0]);
109
		}
110
		return null;
111
	}
112
113
	@Override
114
	protected int[] getTypeIds() {
115
		return new int[] { fTransferId };
116
	}
117
118
	@Override
119
	protected String[] getTypeNames() {
120
		return new String[] { fTransferName };
121
	}
122
123
	@Override
124
	protected boolean validate(Object object) {
125
		return checkProposalTransferType(object);
126
	}
127
128
	public int getCompatibleOperation(int operation, int supportedOperations, TransferData currentDataType) {
129
		if (this.isSupportedType(currentDataType)) {
130
			if (operation == DND.DROP_DEFAULT)
131
				return this.getDefaultOperation(supportedOperations);
132
			if (this.isSupportedOperation(operation) && (supportedOperations & operation) != 0)
133
				return operation;
134
			return DND.DROP_NONE;
135
		}
136
		return -1;
137
	}
138
139
	private boolean checkProposalTransferType(Object object) {
140
		if (object == null || !(object instanceof ProposalTransferType[]) || ((ProposalTransferType[]) object).length == 0)
141
			return false;
142
		ProposalTransferType[] cats= (ProposalTransferType[]) object;
143
		for (ProposalTransferType category : cats)
144
			if (category == null || ((category.getCategoryId() == null || category.getCategoryId().length() == 0) && category.getListIndex() == null))
145
				return false;
146
		return true;
147
	}
148
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProposalTransferType.java (+53 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
/**
14
 * 
15
 * @since 3.8
16
 */
17
public final class ProposalTransferType {
18
	private Integer fListIndex;
19
20
	private String fCategoryId;
21
22
	public ProposalTransferType() {
23
	}
24
25
	public ProposalTransferType(String categoryId) {
26
		this.fCategoryId= categoryId;
27
	}
28
29
	public ProposalTransferType(Integer listIndex) {
30
		this.fListIndex= listIndex;
31
	}
32
33
	public ProposalTransferType(String categoryId, Integer listIndex) {
34
		this.fCategoryId= categoryId;
35
		this.fListIndex= listIndex;
36
	}
37
38
	public Integer getListIndex() {
39
		return fListIndex;
40
	}
41
42
	public void setListIndex(Integer listIndex) {
43
		fListIndex= listIndex;
44
	}
45
46
	public String getCategoryId() {
47
		return fCategoryId;
48
	}
49
50
	public void setCategoryId(String categoryId) {
51
		fCategoryId= categoryId;
52
	}
53
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/dnd/ProvidedCategoryTransfer.java (+43 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd;
12
13
import org.eclipse.swt.dnd.DND;
14
15
/**
16
 * 
17
 * @since 3.8
18
 */
19
public final class ProvidedCategoryTransfer extends ProposalTransfer {
20
	private static final String TRANSFER_NAME= "ProvidedCategoryTransfer"; //$NON-NLS-1$
21
22
	private static final ProvidedCategoryTransfer instance= new ProvidedCategoryTransfer();
23
24
	private ProvidedCategoryTransfer() {
25
		super(TRANSFER_NAME);
26
	}
27
28
	public static ProvidedCategoryTransfer getInstance() {
29
		return instance;
30
	}
31
32
	@Override
33
	public int getDefaultOperation(int supportedOperations) {
34
		if ((supportedOperations & DND.DROP_COPY) != 0)
35
			return DND.DROP_COPY;
36
		return DND.DROP_NONE;
37
	}
38
39
	@Override
40
	public boolean isSupportedOperation(int operation) {
41
		return operation == DND.DROP_COPY;
42
	}
43
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/ModelElement.java (+128 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model;
12
13
import java.util.Comparator;
14
import java.util.Set;
15
16
import org.eclipse.swt.graphics.Image;
17
18
import org.eclipse.core.commands.Command;
19
import org.eclipse.core.commands.IParameter;
20
import org.eclipse.core.commands.Parameterization;
21
import org.eclipse.core.commands.ParameterizedCommand;
22
import org.eclipse.core.commands.common.NotDefinedException;
23
24
import org.eclipse.core.runtime.Assert;
25
26
import org.eclipse.jface.viewers.Viewer;
27
import org.eclipse.jface.viewers.ViewerComparator;
28
29
import org.eclipse.ui.PlatformUI;
30
import org.eclipse.ui.commands.ICommandService;
31
32
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
33
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory;
34
35
/**
36
 * 
37
 * @since 3.8
38
 */
39
public final class ModelElement {
40
41
	public static final class ModelElementComparator implements Comparator<ModelElement> {
42
		public int compare(ModelElement o1, ModelElement o2) {
43
			return o1.getName().compareTo(o2.getName());
44
		}
45
	}
46
47
	public static final class ModelElementViewerComparator extends ViewerComparator {
48
		@Override
49
		public int compare(Viewer viewer, Object e1, Object e2) {
50
			ModelElement m1= (ModelElement) e1;
51
			ModelElement m2= (ModelElement) e2;
52
			return new ModelElementComparator().compare(m1, m2);
53
		}
54
	}
55
56
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
57
58
	private final CompletionProposalCategory fCategory;
59
60
	private final Command fCommand;
61
62
	private final IParameter fParam;
63
64
	private final PreferenceModel fPreferenceModel;
65
66
	ModelElement(CompletionProposalCategory category, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
67
		fCategory= category;
68
		ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
69
		fCommand= commandSvc.getCommand("org.eclipse.jdt.ui.specific_content_assist.command"); //$NON-NLS-1$
70
		IParameter type;
71
		try {
72
			type= fCommand.getParameters()[0];
73
		} catch (NotDefinedException x) {
74
			Assert.isTrue(false);
75
			type= null;
76
		}
77
		fParam= type;
78
		fPreferenceModel= model;
79
		fUtilitiesProxy= utilitiesProxy;
80
	}
81
82
	public Image getImage() {
83
		return fUtilitiesProxy.getImage(fCategory.getImageDescriptor());
84
	}
85
86
	public String getName() {
87
		return fCategory.getDisplayName();
88
	}
89
90
	public String getKeybindingAsString() {
91
		final Parameterization[] params= { new Parameterization(fParam, fCategory.getId()) };
92
		final ParameterizedCommand pCmd= new ParameterizedCommand(fCommand, params);
93
		String key= fUtilitiesProxy.getKeyboardShortcut(pCmd);
94
		return key;
95
	}
96
97
	public Set<Integer> getProposalListIndices() {
98
		return fCategory.getProposalListIndices();
99
	}
100
101
	public boolean isInProposalList(int index) {
102
		return getProposalListIndices().contains(Integer.valueOf(index));
103
	}
104
105
	public void setInProposalList(int index) {
106
		if (!isInProposalList(index))
107
			fPreferenceModel.changeSingleCategory(this, Integer.valueOf(index), null);
108
	}
109
110
	public void moveToProposalList(int sourceIndex, int targetIndex) {
111
		if (!isInProposalList(targetIndex) || isInProposalList(sourceIndex))
112
			fPreferenceModel.changeSingleCategory(this, Integer.valueOf(targetIndex), Integer.valueOf(sourceIndex));
113
	}
114
115
	public void removeInProposalList(int index) {
116
		if (isInProposalList(index))
117
			fPreferenceModel.changeSingleCategory(this, null, Integer.valueOf(index));
118
	}
119
120
	public String getId() {
121
		return fCategory.getId();
122
	}
123
124
	void updateIndices(Set<Integer> indices) {
125
		fCategory.clearProposalListIndices();
126
		fCategory.addAllProposalListIndices(indices);
127
	}
128
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/model/PreferenceModel.java (+235 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model;
12
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.StringTokenizer;
21
import java.util.TreeMap;
22
23
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
24
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory;
25
import org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerRegistry;
26
27
/**
28
 * 
29
 * @since 3.8
30
 */
31
public final class PreferenceModel {
32
	private static final String COLON= ":"; //$NON-NLS-1$
33
34
	private static final String SEPARATOR= "\0"; //$NON-NLS-1$
35
36
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
37
38
	private final List<ModelElement> fElements;
39
40
	/**
41
	 * The read-only list of elements.
42
	 */
43
	public final List<ModelElement> elements;
44
45
	public PreferenceModel(CompletionProposalComputerRegistry registry, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
46
		fUtilitiesProxy= utilitiesProxy;
47
		List<CompletionProposalCategory> categories= registry.getProposalCategories();
48
		fElements= new ArrayList<ModelElement>();
49
		for (CompletionProposalCategory category : categories)
50
			if (category.hasComputers())
51
				fElements.add(new ModelElement(category, this, fUtilitiesProxy));
52
		elements= Collections.unmodifiableList(fElements);
53
	}
54
55
	public void changeSingleCategory(ModelElement changed, Integer addIndex, Integer removeIndex) {
56
		int initialBufferSize= 50 * fElements.size();
57
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
58
		for (ModelElement item : fElements) {
59
			Set<Integer> indices= new HashSet<Integer>(item.getProposalListIndices());
60
			if (changed == item) {
61
				if (addIndex != null)
62
					indices.add(addIndex);
63
				if (removeIndex != null)
64
					indices.remove(removeIndex);
65
			}
66
			for (Integer index : indices) {
67
				StringBuffer buf= proposalListsCategories.get(index);
68
				if (buf == null) {
69
					buf= new StringBuffer(initialBufferSize);
70
					proposalListsCategories.put(index, buf);
71
				}
72
				buf.append(item.getId());
73
				buf.append(COLON);
74
			}
75
		}
76
		writeProposalListsPreferences(proposalListsCategories, initialBufferSize);
77
	}
78
79
	public void removeList(int listIndex) {
80
		int initialBufferSize= 50 * fElements.size();
81
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
82
		for (ModelElement item : fElements) {
83
			for (int index : item.getProposalListIndices()) {
84
				if (listIndex == index)
85
					continue;
86
				else if (index > listIndex)
87
					index--;
88
				StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index));
89
				if (buf == null) {
90
					buf= new StringBuffer(initialBufferSize);
91
					proposalListsCategories.put(Integer.valueOf(index), buf);
92
				}
93
				buf.append(item.getId());
94
				buf.append(COLON);
95
			}
96
		}
97
		writeProposalListsPreferences(proposalListsCategories, initialBufferSize);
98
	}
99
100
	public void addNewList(int listIndex, List<String> categoryIds) {
101
		int initialBufferSize= 50 * fElements.size();
102
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
103
		for (ModelElement item : fElements) {
104
			for (int index : item.getProposalListIndices()) {
105
				if (index >= listIndex)
106
					index++;
107
				StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index));
108
				if (buf == null) {
109
					buf= new StringBuffer(initialBufferSize);
110
					proposalListsCategories.put(Integer.valueOf(index), buf);
111
				}
112
				buf.append(item.getId());
113
				buf.append(COLON);
114
			}
115
		}
116
		if (categoryIds != null && !categoryIds.isEmpty()) {
117
			// add categories to new list 
118
			StringBuffer newListBuf= new StringBuffer(initialBufferSize);
119
			proposalListsCategories.put(Integer.valueOf(listIndex), newListBuf);
120
			for (String catId : categoryIds) {
121
				newListBuf.append(catId);
122
				newListBuf.append(COLON);
123
			}
124
		}
125
		writeProposalListsPreferences(proposalListsCategories, initialBufferSize);
126
	}
127
128
	public void moveList(int listIndex, int targetIndex) {
129
		int initialBufferSize= 50 * fElements.size();
130
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
131
		for (ModelElement item : fElements) {
132
			for (int index : item.getProposalListIndices()) {
133
				if (index > listIndex && index < targetIndex)
134
					index--;
135
				else if (index >= targetIndex && index < listIndex)
136
					index++;
137
				else if (index == listIndex)
138
					index= listIndex < targetIndex ? targetIndex - 1 : targetIndex;
139
				StringBuffer buf= proposalListsCategories.get(Integer.valueOf(index));
140
				if (buf == null) {
141
					buf= new StringBuffer(initialBufferSize);
142
					proposalListsCategories.put(Integer.valueOf(index), buf);
143
				}
144
				buf.append(item.getId());
145
				buf.append(COLON);
146
			}
147
		}
148
		writeProposalListsPreferences(proposalListsCategories, initialBufferSize);
149
	}
150
151
	public void mergeLists(int sourceIndex, int targetIndex, boolean removeSource) {
152
		int initialBufferSize= 50 * fElements.size();
153
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
154
		for (ModelElement item : fElements) {
155
			Set<Integer> indices= new HashSet<Integer>(item.getProposalListIndices());
156
			if (indices.contains(Integer.valueOf(sourceIndex))) {
157
				if (removeSource)
158
					indices.remove(Integer.valueOf(sourceIndex));
159
				indices.add(Integer.valueOf(targetIndex));
160
			}
161
			for (Integer index : indices) {
162
				StringBuffer buf= proposalListsCategories.get(index);
163
				if (buf == null) {
164
					buf= new StringBuffer(initialBufferSize);
165
					proposalListsCategories.put(index, buf);
166
				}
167
				buf.append(item.getId());
168
				buf.append(COLON);
169
			}
170
		}
171
		writeProposalListsPreferences(proposalListsCategories, initialBufferSize);
172
	}
173
174
	private void writeProposalListsPreferences(Map<Integer, StringBuffer> proposalListsCategories, int initialBufferSize) {
175
		StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size());
176
		for (StringBuffer proposalList : proposalListsCategories.values()) {
177
			buf.append(proposalList);
178
			buf.append(SEPARATOR);
179
		}
180
		String newValue= buf.toString();
181
		String oldValue= fUtilitiesProxy.setValue(newValue);
182
		fUtilitiesProxy.validateSettings(oldValue, newValue);
183
		updatePreferenceModel();
184
	}
185
186
	public void updatePreferenceModel() {
187
		Map<String, Set<Integer>> newConfig= new HashMap<String, Set<Integer>>();
188
		StringTokenizer tok= new StringTokenizer(fUtilitiesProxy.getValue(), SEPARATOR);
189
		for (int listIndex= 0; tok.hasMoreTokens(); listIndex++) {
190
			StringTokenizer inner= new StringTokenizer(tok.nextToken(), COLON);
191
			if (inner.countTokens() == 0)
192
				listIndex--;
193
			while (inner.hasMoreTokens()) {
194
				String categoryId= inner.nextToken();
195
				Set<Integer> indices= newConfig.get(categoryId);
196
				if (indices == null) {
197
					indices= new HashSet<Integer>();
198
					newConfig.put(categoryId, indices);
199
				}
200
				indices.add(Integer.valueOf(listIndex));
201
			}
202
		}
203
		for (ModelElement elem : fElements)
204
			elem.updateIndices(newConfig.get(elem.getId()));
205
	}
206
207
	public ModelElement getElement(String id) {
208
		for (ModelElement el : fElements)
209
			if (el.getId().equals(id))
210
				return el;
211
		return null;
212
	}
213
214
	public List<ModelElement> getElements(int index) {
215
		List<ModelElement> result= new ArrayList<ModelElement>();
216
		for (ModelElement el : fElements)
217
			if (el.getProposalListIndices() != null && el.getProposalListIndices().contains(Integer.valueOf(index)))
218
				result.add(el);
219
		return result;
220
	}
221
222
	public List<String> getCategoryIds(int index) {
223
		List<String> result= new ArrayList<String>();
224
		for (ModelElement el : fElements)
225
			if (el.getProposalListIndices() != null && el.getProposalListIndices().contains(Integer.valueOf(index)))
226
				result.add(el.getId());
227
		return result;
228
	}
229
230
	public boolean isValidCategoryId(String id) {
231
		if (id != null)
232
			return getElement(id) != null;
233
		return false;
234
	}
235
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/NewListDropSection.java (+93 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets;
12
13
import org.eclipse.swt.SWT;
14
import org.eclipse.swt.dnd.DropTarget;
15
import org.eclipse.swt.dnd.Transfer;
16
import org.eclipse.swt.layout.GridData;
17
import org.eclipse.swt.layout.GridLayout;
18
import org.eclipse.swt.widgets.Composite;
19
20
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
21
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropNewProposalListListener;
22
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer;
23
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
24
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer;
25
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer;
26
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
27
28
/**
29
 * 
30
 * @since 3.8
31
 */
32
public final class NewListDropSection {
33
	private final PreferenceModel fModel;
34
35
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
36
37
	private final ProposalListSection fProposalListSection;
38
39
	private final Composite fPaddingComposite;
40
41
	private final Composite fHighlightComposite;
42
43
	public NewListDropSection(Composite wrappingComposite, int listIndex, PreferenceModel model, ProposalListSection proposalListSection, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
44
		this.fModel= model;
45
		this.fUtilitiesProxy= utilitiesProxy;
46
		this.fProposalListSection= proposalListSection;
47
48
		fPaddingComposite= createPaddingComposite(wrappingComposite);
49
		fHighlightComposite= createHighlightComposite(fPaddingComposite);
50
51
		addDropSupport(fPaddingComposite, fHighlightComposite, listIndex);
52
	}
53
54
	public void activateLastPositionSpaceBehavior(boolean last) {
55
		GridData gd= new GridData(GridData.FILL, GridData.FILL, true, last);
56
		gd.heightHint= 10;
57
		fPaddingComposite.setLayoutData(gd);
58
	}
59
60
	public void dispose() {
61
		fPaddingComposite.dispose();
62
		fHighlightComposite.dispose();
63
	}
64
65
	private Composite createPaddingComposite(Composite wrappingComposite) {
66
		Composite paddingComposite= new Composite(wrappingComposite, SWT.NONE);
67
		GridData gd= new GridData(GridData.FILL, GridData.BEGINNING, true, false);
68
		gd.heightHint= 10;
69
		paddingComposite.setLayoutData(gd);
70
		GridLayout layout= new GridLayout();
71
		layout.marginHeight= 0;
72
		layout.verticalSpacing= 0;
73
		layout.marginWidth= 0;
74
		paddingComposite.setLayout(layout);
75
		return paddingComposite;
76
	}
77
78
	private Composite createHighlightComposite(Composite paddingComposite) {
79
		Composite highlightComposite= new Composite(paddingComposite, SWT.NONE);
80
		GridData gd= new GridData(SWT.FILL, SWT.BEGINNING, true, true);
81
		gd.heightHint= 2;
82
		gd.verticalIndent= 4;
83
		highlightComposite.setLayoutData(gd);
84
		return highlightComposite;
85
	}
86
87
	private void addDropSupport(Composite paddingComposite, Composite highlightComposite, int listIndex) {
88
		Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() };
89
		DropTarget dropTarget= new DropTarget(paddingComposite, ProposalTransfer.ALL_DRAG_OPERATIONS);
90
		dropTarget.setTransfer(transferTypes);
91
		dropTarget.addDropListener(new DropNewProposalListListener(highlightComposite, listIndex, fModel, fUtilitiesProxy, fProposalListSection));
92
	}
93
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalList.java (+421 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets;
12
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.List;
16
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.dnd.DropTarget;
19
import org.eclipse.swt.dnd.Transfer;
20
import org.eclipse.swt.events.MouseEvent;
21
import org.eclipse.swt.events.MouseListener;
22
import org.eclipse.swt.events.PaintEvent;
23
import org.eclipse.swt.events.PaintListener;
24
import org.eclipse.swt.graphics.GC;
25
import org.eclipse.swt.graphics.Image;
26
import org.eclipse.swt.graphics.ImageData;
27
import org.eclipse.swt.graphics.Point;
28
import org.eclipse.swt.graphics.Rectangle;
29
import org.eclipse.swt.layout.GridData;
30
import org.eclipse.swt.layout.GridLayout;
31
import org.eclipse.swt.widgets.Composite;
32
import org.eclipse.swt.widgets.Event;
33
import org.eclipse.swt.widgets.Listener;
34
import org.eclipse.swt.widgets.Table;
35
import org.eclipse.swt.widgets.TableColumn;
36
import org.eclipse.swt.widgets.TableItem;
37
38
import org.eclipse.core.runtime.Assert;
39
40
import org.eclipse.jface.viewers.IStructuredContentProvider;
41
import org.eclipse.jface.viewers.ITableLabelProvider;
42
import org.eclipse.jface.viewers.LabelProvider;
43
import org.eclipse.jface.viewers.TableViewer;
44
import org.eclipse.jface.viewers.Viewer;
45
46
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
47
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProposalListCategoryListener;
48
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DropIntoProposalListListener;
49
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer;
50
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
51
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer;
52
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer;
53
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement;
54
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
55
56
/**
57
 * 
58
 * @since 3.8
59
 */
60
public final class ProposalList {
61
62
	private final class ProposalListTableLabelProvider extends LabelProvider implements ITableLabelProvider {
63
64
		/*
65
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
66
		 */
67
		public Image getColumnImage(Object element, int columnIndex) {
68
			if (columnIndex == 0)
69
				return ((ModelElement) element).getImage();
70
			return null;
71
		}
72
73
		/*
74
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
75
		 */
76
		public String getColumnText(Object element, int columnIndex) {
77
			switch (columnIndex) {
78
				case 0:
79
					return ((ModelElement) element).getName();
80
				default:
81
					Assert.isTrue(false);
82
					return null;
83
			}
84
		}
85
	}
86
87
	private final class ProposalListContentProvider implements IStructuredContentProvider {
88
		private final int fListIndex;
89
90
		public ProposalListContentProvider(int listIndex) {
91
			this.fListIndex= listIndex;
92
		}
93
94
		public void dispose() {
95
		}
96
97
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
98
		}
99
100
		public Object[] getElements(Object inputElement) {
101
			return fModel.getElements(fListIndex).toArray();
102
		}
103
	}
104
105
	private final PreferenceModel fModel;
106
107
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
108
109
	private final ProposalListSection fProposalListSection;
110
111
	private final Composite fTableContainer;
112
113
	private final ProposalListHeader fHeader;
114
115
	private final TableViewer fTableViewer;
116
117
	private final NewListDropSection fNewListDropSection;
118
119
	private boolean fSelected;
120
121
	public ProposalList(Composite parent, int listIndex, ProposalListSection proposalListSection, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
122
		this.fModel= model;
123
		this.fUtilitiesProxy= utilitiesProxy;
124
		this.fProposalListSection= proposalListSection;
125
126
		fTableContainer= createTableContainer(parent);
127
		fHeader= new ProposalListHeader(fTableContainer, listIndex, fModel, fUtilitiesProxy);
128
		fTableViewer= createTable(fTableContainer, listIndex);
129
130
		fNewListDropSection= new NewListDropSection(parent, listIndex + 1, fModel, fProposalListSection, fUtilitiesProxy);
131
132
		addDropSupport(fTableContainer, listIndex);
133
		addRemoveIconVisibility();
134
		addBorderPainter(fTableContainer);
135
	}
136
137
	@SuppressWarnings("unchecked")
138
	public List<ModelElement> getContent() {
139
		Object obj= fTableViewer.getInput();
140
		if (obj == null)
141
			return null;
142
		return (List<ModelElement>) obj;
143
	}
144
145
	public void clearContent() {
146
		fTableViewer.setInput(null);
147
	}
148
149
	public void addContent(ModelElement element) {
150
		List<ModelElement> content= getContent();
151
		if (content == null)
152
			content= new ArrayList<ModelElement>();
153
		content.add(element);
154
		setContent(content);
155
	}
156
157
	public void setContent(List<ModelElement> elements) {
158
		fTableViewer.setInput(elements);
159
	}
160
161
	public void activateLastListSpaceBehavior(boolean last) {
162
		fNewListDropSection.activateLastPositionSpaceBehavior(last);
163
	}
164
165
	public void dispose() {
166
		fTableContainer.dispose();
167
		fHeader.dispose();
168
		fTableViewer.getTable().dispose();
169
		fNewListDropSection.dispose();
170
	}
171
172
	public void highlight(boolean highlight) {
173
		if (fSelected == highlight)
174
			return;
175
		fSelected= highlight;
176
		fTableContainer.redraw();
177
178
		fHeader.highlight(highlight);
179
	}
180
181
	private Composite createTableContainer(Composite parent) {
182
		Composite tableContainer= new Composite(parent, SWT.NONE);
183
		tableContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
184
		GridLayout layout= new GridLayout();
185
		layout.marginHeight= 1;
186
		layout.marginWidth= 1;
187
		layout.verticalSpacing= 0;
188
		layout.horizontalSpacing= 0;
189
		tableContainer.setLayout(layout);
190
		return tableContainer;
191
	}
192
193
	private TableViewer createTable(Composite tableContainer, final int listIndex) {
194
		TableViewer tableViewer= createInitialTableViewer(tableContainer);
195
		TableColumn nameColumn= addFirstColumn(tableViewer);
196
197
		ITableLabelProvider labelProvider= setProviderAndComparator(tableViewer, listIndex);
198
		adjustFirstColumnWidth(nameColumn, tableViewer, labelProvider);
199
200
		addDragSupport(tableViewer, listIndex);
201
		addFocusOutListener(tableViewer);
202
		addProposalListCategoryRemoveIconCreator(tableViewer, listIndex);
203
204
		return tableViewer;
205
	}
206
207
	private void addDropSupport(Composite tableContainer, int listIndex) {
208
		Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() };
209
		DropTarget dropTarget= new DropTarget(tableContainer, ProposalTransfer.ALL_DRAG_OPERATIONS);
210
		dropTarget.setTransfer(transferTypes);
211
		dropTarget.addDropListener(new DropIntoProposalListListener(this, listIndex, fModel, fUtilitiesProxy, fProposalListSection));
212
	}
213
214
	private void addRemoveIconVisibility() {
215
		Listener l= new Listener() {
216
			public void handleEvent(Event e) {
217
				fHeader.showRemoveIcon();
218
			}
219
		};
220
		this.addListener(SWT.MouseEnter, l);
221
		this.addListener(SWT.MouseMove, l);
222
		this.addListener(SWT.MouseExit, new Listener() {
223
			public void handleEvent(Event e) {
224
				fHeader.hideRemoveIcon();
225
			}
226
		});
227
	}
228
229
	private void addBorderPainter(final Composite tableContainer) {
230
		tableContainer.addPaintListener(new PaintListener() {
231
			public void paintControl(PaintEvent e) {
232
				if (fSelected)
233
					e.gc.setBackground(CodeAssistAdvancedUtilitiesProxy.SELECTED_COLOR);
234
				else
235
					e.gc.setBackground(CodeAssistAdvancedUtilitiesProxy.UNSELECTED_BORDER_COLOR);
236
				Rectangle rect= tableContainer.getClientArea();
237
				e.gc.fillRectangle(rect);
238
			}
239
		});
240
	}
241
242
	private TableViewer createInitialTableViewer(Composite tableContainer) {
243
		TableViewer listViewer= new TableViewer(tableContainer, SWT.SINGLE | SWT.NO_SCROLL);
244
		final Table table= listViewer.getTable();
245
		table.setHeaderVisible(false);
246
		table.setLinesVisible(false);
247
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
248
		return listViewer;
249
	}
250
251
	private TableColumn addFirstColumn(TableViewer tableViewer) {
252
		TableColumn nameColumn= new TableColumn(tableViewer.getTable(), SWT.NONE);
253
		nameColumn.setResizable(false);
254
		return nameColumn;
255
	}
256
257
	private void adjustFirstColumnWidth(TableColumn column, TableViewer tableViewer, ITableLabelProvider labelProvider) {
258
		final int ICON_WIDTH= 16;
259
		final int HEADER_MARGIN= 20;
260
		int minNameWidth= fUtilitiesProxy.computeWidth(tableViewer.getTable(), column.getText()) + HEADER_MARGIN;
261
		for (int i= 0; i < fModel.elements.size(); i++) {
262
			minNameWidth= Math.max(minNameWidth, fUtilitiesProxy.computeWidth(tableViewer.getTable(), labelProvider.getColumnText(fModel.elements.get(i), 0)) + 2 * ICON_WIDTH);
263
		}
264
		column.setWidth(minNameWidth);
265
	}
266
267
	private ITableLabelProvider setProviderAndComparator(TableViewer tableViewer, int listIndex) {
268
		tableViewer.setContentProvider(new ProposalListContentProvider(listIndex));
269
		tableViewer.setComparator(new ModelElement.ModelElementViewerComparator());
270
		ITableLabelProvider labelProvider= new ProposalListTableLabelProvider();
271
		tableViewer.setLabelProvider(labelProvider);
272
		return labelProvider;
273
	}
274
275
	private void addDragSupport(TableViewer tableViewer, int listIndex) {
276
		Transfer[] transferTypes= new Transfer[] { ProposalListCategoryTransfer.getInstance() };
277
		tableViewer.addDragSupport(ProposalTransfer.ALL_DRAG_OPERATIONS, transferTypes, new DragProposalListCategoryListener(tableViewer, listIndex));
278
	}
279
280
	private void addFocusOutListener(TableViewer tableViewer) {
281
		final Table table= tableViewer.getTable();
282
		table.addListener(SWT.FocusOut, new Listener() {
283
			public void handleEvent(Event event) {
284
				table.deselectAll();
285
			}
286
		});
287
	}
288
289
	private void addListener(int eventType, Listener listener) {
290
		fTableContainer.addListener(eventType, listener);
291
		fHeader.addListener(eventType, listener);
292
		fTableViewer.getTable().addListener(eventType, listener);
293
	}
294
295
	private void addProposalListCategoryRemoveIconCreator(final TableViewer tableViewer, final int listIndex) {
296
		Table table= tableViewer.getTable();
297
		Rectangle iconRect= addRemoveIconToItemsPainter(table);
298
		addRemoveIconRedrawListener(table, iconRect);
299
		addRemoveCategoryOnClickListener(table, iconRect, listIndex);
300
	}
301
302
	private Rectangle addRemoveIconToItemsPainter(Table table) {
303
		final Rectangle iconRect= new Rectangle(0, 0, 0, 0);
304
		Listener paintListener= new Listener() {
305
			public void handleEvent(Event event) {
306
				Table tab= ((Table) event.widget);
307
				Point tabLoc= getTableLocation(tab);
308
				Point mouseLoc= getMouseLocation(tab, tabLoc);
309
				if (isMouseOverCurrentRow(tab, mouseLoc, (TableItem) event.item)) {
310
					updateIconRectangle(tab, event.height, event.y);
311
					drawIcon(event.gc, mouseLoc);
312
				}
313
			}
314
315
			private Point getTableLocation(Table tab) {
316
				return tab.toDisplay(tab.getClientArea().x, tab.getClientArea().y);
317
			}
318
319
			private Point getMouseLocation(Table tab, Point tabLoc) {
320
				Point mouseLoc= tab.getDisplay().getCursorLocation();
321
				mouseLoc= new Point(mouseLoc.x - tabLoc.x, mouseLoc.y - tabLoc.y);
322
				return mouseLoc;
323
			}
324
325
			private boolean isMouseOverCurrentRow(Table tab, Point mouseLoc, TableItem currentItem) {
326
				return tab.getClientArea().contains(mouseLoc) && currentItem == getItem(tab, mouseLoc);
327
			}
328
329
			private void updateIconRectangle(Table tab, int eventHeight, int eventY) {
330
				ImageData imgData= fUtilitiesProxy.fRemoveProposalListImage.getImageData();
331
				int x= tab.getClientArea().width - imgData.width;
332
				int offset= Math.max(0, (eventHeight - imgData.height) / 2);
333
334
				iconRect.height= imgData.height;
335
				iconRect.width= imgData.width;
336
				iconRect.x= x;
337
				iconRect.y= eventY + offset;
338
			}
339
340
			private void drawIcon(GC gc, Point mouseLoc) {
341
				gc.setClipping(iconRect);
342
				if (iconRect.contains(mouseLoc))
343
					gc.drawImage(fUtilitiesProxy.fRemoveProposalListOverImage, iconRect.x, iconRect.y);
344
				else
345
					gc.drawImage(fUtilitiesProxy.fRemoveProposalListImage, iconRect.x, iconRect.y);
346
			}
347
		};
348
		table.addListener(SWT.PaintItem, paintListener);
349
		return iconRect;
350
	}
351
352
	private void addRemoveIconRedrawListener(final Table table, final Rectangle iconRect) {
353
		Listener mouseOverTableListener= new Listener() {
354
			TableItem lastItem;
355
356
			boolean lastOverImg;
357
358
			public void handleEvent(Event e) {
359
				TableItem item= getItem(table, new Point(e.x, e.y));
360
				boolean overImg= iconRect.contains(e.x, e.y);
361
				if (lastItem != item || lastOverImg != overImg) {
362
					lastItem= item;
363
					lastOverImg= overImg;
364
					table.redraw();
365
				}
366
			}
367
		};
368
		table.addListener(SWT.MouseEnter, mouseOverTableListener);
369
		table.addListener(SWT.MouseMove, mouseOverTableListener);
370
		table.addListener(SWT.MouseExit, mouseOverTableListener);
371
	}
372
373
	private void addRemoveCategoryOnClickListener(final Table table, final Rectangle iconRect, final int listIndex) {
374
		table.addMouseListener(new MouseListener() {
375
			public void mouseUp(MouseEvent e) {
376
				if (isSingleClick(e.count) && isUpOverIcon(e.x, e.y)) {
377
					int elemIndex= table.indexOf(getItem(table, new Point(e.x, e.y)));
378
					List<ModelElement> categories= fModel.getElements(listIndex);
379
					Collections.sort(categories, new ModelElement.ModelElementComparator());
380
					categories.get(elemIndex).removeInProposalList(listIndex);
381
					fUtilitiesProxy.updateControls();
382
				}
383
			}
384
385
			public void mouseDown(MouseEvent e) {
386
			}
387
388
			public void mouseDoubleClick(MouseEvent e) {
389
			}
390
391
			private boolean isSingleClick(int count) {
392
				return count == 1;
393
			}
394
395
			private boolean isUpOverIcon(int x, int y) {
396
				return iconRect.contains(x, y);
397
			}
398
		});
399
	}
400
401
	private TableItem getItem(Table tab, Point p) {
402
		for (int index= 0; index < tab.getItemCount(); index++) {
403
			if (getItemBounds(tab, index).contains(p))
404
				return tab.getItem(index);
405
		}
406
		return null;
407
	}
408
409
	private Rectangle getItemBounds(Table tab, int itemIndex) {
410
		Rectangle tableBounds= tab.getBounds();
411
		int height= tab.getItemHeight();
412
		int width= tableBounds.width;
413
		int x= tableBounds.x;
414
		int y= itemIndex * height;
415
		return new Rectangle(x, y, width, height);
416
	}
417
418
	public TableViewer getTableViewer() {
419
		return fTableViewer;
420
	}
421
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListHeader.java (+197 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets;
12
13
import org.eclipse.swt.SWT;
14
import org.eclipse.swt.dnd.DragSource;
15
import org.eclipse.swt.dnd.DragSourceListener;
16
import org.eclipse.swt.dnd.Transfer;
17
import org.eclipse.swt.events.MouseEvent;
18
import org.eclipse.swt.events.MouseListener;
19
import org.eclipse.swt.graphics.Color;
20
import org.eclipse.swt.layout.GridData;
21
import org.eclipse.swt.layout.GridLayout;
22
import org.eclipse.swt.widgets.Composite;
23
import org.eclipse.swt.widgets.Control;
24
import org.eclipse.swt.widgets.Display;
25
import org.eclipse.swt.widgets.Event;
26
import org.eclipse.swt.widgets.Label;
27
import org.eclipse.swt.widgets.Listener;
28
29
import org.eclipse.jdt.internal.corext.util.Messages;
30
31
import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages;
32
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
33
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.DragProposalListListener;
34
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
35
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer;
36
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
37
38
/**
39
 * 
40
 * @since 3.8
41
 */
42
public final class ProposalListHeader {
43
44
	private static final Color SELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION);
45
46
	private static final Color SELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
47
48
	private static final Color UNSELECTED_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
49
50
	private static final Color UNSELECTED_TEXT_COLOR= Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
51
52
	private final PreferenceModel fModel;
53
54
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
55
56
	private final Composite fPaddingComposite;
57
58
	private final Label fTitle;
59
60
	private final Label fRemoveLabel;
61
62
	public ProposalListHeader(Composite tableContainer, int listIndex, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
63
		this.fModel= model;
64
		this.fUtilitiesProxy= utilitiesProxy;
65
66
		fPaddingComposite= createPaddingComposite(tableContainer);
67
		fTitle= createTitle(fPaddingComposite, listIndex);
68
		fRemoveLabel= createRemoveIcon(fPaddingComposite, listIndex);
69
		updateHeaderHeight();
70
71
		addListDragSupport(fPaddingComposite, listIndex);
72
		addListDragSupport(fTitle, listIndex);
73
	}
74
75
	public void dispose() {
76
		fPaddingComposite.dispose();
77
		fTitle.dispose();
78
		fRemoveLabel.dispose();
79
	}
80
81
	public void highlight(boolean highlight) {
82
		Color backgroundColor= highlight ? SELECTED_COLOR : UNSELECTED_COLOR;
83
		Color foregroundColor= highlight ? SELECTED_TEXT_COLOR : UNSELECTED_TEXT_COLOR;
84
		fPaddingComposite.setBackground(backgroundColor);
85
		fTitle.setBackground(backgroundColor);
86
		fTitle.setForeground(foregroundColor);
87
		fRemoveLabel.setBackground(backgroundColor);
88
	}
89
90
	public void showRemoveIcon() {
91
		fRemoveLabel.setVisible(true);
92
	}
93
94
	public void hideRemoveIcon() {
95
		fRemoveLabel.setVisible(false);
96
	}
97
98
	public void addListener(int eventType, Listener listener) {
99
		fPaddingComposite.addListener(eventType, listener);
100
		fTitle.addListener(eventType, listener);
101
		fRemoveLabel.addListener(eventType, listener);
102
	}
103
104
	private Composite createPaddingComposite(Composite tableContainer) {
105
		Composite paddingComposite= new Composite(tableContainer, SWT.NONE);
106
		GridLayout layout= new GridLayout(2, false);
107
		layout.marginHeight= 0;
108
		layout.verticalSpacing= 0;
109
		paddingComposite.setLayout(layout);
110
		return paddingComposite;
111
	}
112
113
	private Label createTitle(Composite paddingComposite, int listIndex) {
114
		Label title= new Label(paddingComposite, SWT.NONE);
115
		title.setText(getProposalListTitle(listIndex));
116
		title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
117
		return title;
118
	}
119
120
	private void updateHeaderHeight() {
121
		GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
122
		gd.heightHint= getHeaderHeight();
123
		fPaddingComposite.setLayoutData(gd);
124
	}
125
126
	private Label createRemoveIcon(final Composite paddingComposite, final int listIndex) {
127
		final Label removeLabel= createRemoveLabel(paddingComposite);
128
		addMouseOverIconListener(removeLabel);
129
		addRemoveListOnClickListener(removeLabel, listIndex);
130
		return removeLabel;
131
	}
132
133
	private void addListDragSupport(Control control, int listIndex) {
134
		DragSourceListener tableDragSourceListener= new DragProposalListListener(listIndex);
135
		Transfer[] transferTypes= new Transfer[] { ProposalListTransfer.getInstance() };
136
		DragSource dragSource= new DragSource(control, ProposalTransfer.ALL_DRAG_OPERATIONS);
137
		dragSource.setTransfer(transferTypes);
138
		dragSource.addDragListener(tableDragSourceListener);
139
	}
140
141
	private String getProposalListTitle(int index) {
142
		return Messages.format(PreferencesMessages.CodeAssistAdvancedConfigurationBlock_proposal_list_table_title, Integer.valueOf(index + 1));
143
	}
144
145
	private int getHeaderHeight() {
146
		return fTitle.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + 8;
147
	}
148
149
	private Label createRemoveLabel(Composite paddingComposite) {
150
		final Label removeLabel= new Label(paddingComposite, SWT.NONE);
151
		removeLabel.setVisible(false);
152
		removeLabel.setImage(fUtilitiesProxy.fRemoveProposalListImage);
153
		GridData gd= new GridData(SWT.RIGHT, SWT.CENTER, true, true);
154
		gd.widthHint= fUtilitiesProxy.fRemoveProposalListImage.getImageData().width;
155
		gd.minimumWidth= gd.widthHint;
156
		removeLabel.setLayoutData(gd);
157
		return removeLabel;
158
	}
159
160
	private void addMouseOverIconListener(final Label removeLabel) {
161
		removeLabel.addListener(SWT.MouseEnter, new Listener() {
162
			public void handleEvent(Event e) {
163
				removeLabel.setImage(fUtilitiesProxy.fRemoveProposalListOverImage);
164
			}
165
		});
166
		removeLabel.addListener(SWT.MouseExit, new Listener() {
167
			public void handleEvent(Event e) {
168
				removeLabel.setImage(fUtilitiesProxy.fRemoveProposalListImage);
169
			}
170
		});
171
	}
172
173
	private void addRemoveListOnClickListener(final Label removeLabel, final int listIndex) {
174
		removeLabel.addMouseListener(new MouseListener() {
175
			public void mouseUp(MouseEvent e) {
176
				if (isSingleClick(e.count) && isUpOverIcon(e.x, e.y)) {
177
					fModel.removeList(listIndex);
178
					fUtilitiesProxy.updateControls();
179
				}
180
			}
181
182
			public void mouseDown(MouseEvent e) {
183
			}
184
185
			public void mouseDoubleClick(MouseEvent e) {
186
			}
187
188
			private boolean isSingleClick(int count) {
189
				return count == 1;
190
			}
191
192
			private boolean isUpOverIcon(int x, int y) {
193
				return x >= 0 && x < removeLabel.getBounds().width && y >= 0 && y < removeLabel.getBounds().height;
194
			}
195
		});
196
	}
197
}
(-)ui/org/eclipse/jdt/internal/ui/preferences/codeassist/advanced/widgets/ProposalListSection.java (+194 lines)
Added Link Here
1
/**
2
 * Copyright (c) 2011 Thomas Schlosser.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *    Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - initial API and implementation.
10
 */
11
package org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.widgets;
12
13
import java.util.ArrayList;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17
18
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.custom.ScrolledComposite;
20
import org.eclipse.swt.dnd.DropTarget;
21
import org.eclipse.swt.dnd.DropTargetEvent;
22
import org.eclipse.swt.dnd.Transfer;
23
import org.eclipse.swt.events.ControlEvent;
24
import org.eclipse.swt.events.ControlListener;
25
import org.eclipse.swt.graphics.Point;
26
import org.eclipse.swt.graphics.Rectangle;
27
import org.eclipse.swt.layout.GridData;
28
import org.eclipse.swt.layout.GridLayout;
29
import org.eclipse.swt.widgets.Composite;
30
31
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.CodeAssistAdvancedUtilitiesProxy;
32
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.AutoscrollDropTargetListener;
33
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListCategoryTransfer;
34
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalListTransfer;
35
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProposalTransfer;
36
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.dnd.ProvidedCategoryTransfer;
37
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.ModelElement;
38
import org.eclipse.jdt.internal.ui.preferences.codeassist.advanced.model.PreferenceModel;
39
40
/**
41
 * 
42
 * @since 3.8
43
 */
44
public final class ProposalListSection {
45
	private final PreferenceModel fModel;
46
47
	private final CodeAssistAdvancedUtilitiesProxy fUtilitiesProxy;
48
49
	private final ScrolledComposite fScrolledComposite;
50
51
	private final Composite fInnerWrappingComposite;
52
53
	private final List<ProposalList> fProposalLists= new ArrayList<ProposalList>();
54
55
	public ProposalListSection(Composite parent, PreferenceModel model, CodeAssistAdvancedUtilitiesProxy utilitiesProxy) {
56
		this.fModel= model;
57
		this.fUtilitiesProxy= utilitiesProxy;
58
59
		fScrolledComposite= createOuterScrolledComposite(parent);
60
		addDropAutoScroll(fScrolledComposite);
61
		fInnerWrappingComposite= createInnerProposalListWrappingComposite(fScrolledComposite);
62
63
		addOuterSizeUpdater(fScrolledComposite, fInnerWrappingComposite);
64
65
		createFirstNewListDropSection(fInnerWrappingComposite);
66
	}
67
68
	public void updateControls() {
69
		//FIXME: This fixes the problem of refreshing the first list when first element (category) has been added.
70
		// This bug only occurs when the configuration page has been opened indirectly.
71
		// If the "Content Assist"->"Advanced" page is opened directly, it behaves as expected.
72
		if (fProposalLists.size() == 1 && fProposalLists.get(0).getContent() == null) {
73
			fProposalLists.get(0).dispose();
74
			fProposalLists.remove(0);
75
		}
76
		clearOldListState();
77
		Set<Integer> filledLists= updateListStates();
78
		makeSureFirstListExists();
79
		adjustAndCleanUp(filledLists);
80
		reLayoutInnerComposite();
81
	}
82
83
	public void autoScroll(DropTargetEvent event) {
84
		Rectangle area= fScrolledComposite.getClientArea();
85
		Point absoluteLocation= fScrolledComposite.toDisplay(1, 1);
86
		Point origin= fScrolledComposite.getOrigin();
87
		Rectangle bounds= fInnerWrappingComposite.getBounds();
88
89
		int scrollDetectRange= 15;
90
		int offset= 5;
91
		if (absoluteLocation.y + scrollDetectRange > event.y)
92
			origin.y= Math.max(0, origin.y - offset);
93
		if (absoluteLocation.y + area.height - scrollDetectRange < event.y)
94
			origin.y= Math.min(bounds.height - area.height, origin.y + offset);
95
		fScrolledComposite.setOrigin(origin);
96
	}
97
98
	private ScrolledComposite createOuterScrolledComposite(Composite parent) {
99
		ScrolledComposite scrolledComposite= new ScrolledComposite(parent, SWT.V_SCROLL | SWT.BORDER);
100
		scrolledComposite.setAlwaysShowScrollBars(true);
101
		scrolledComposite.setExpandHorizontal(true);
102
		scrolledComposite.setExpandVertical(true);
103
		GridData gridData= new GridData(GridData.FILL, GridData.FILL, true, true);
104
		gridData.heightHint= 0;
105
		scrolledComposite.setLayoutData(gridData);
106
		return scrolledComposite;
107
	}
108
109
	private void addDropAutoScroll(Composite composite) {
110
		Transfer[] transferTypes= new Transfer[] { ProvidedCategoryTransfer.getInstance(), ProposalListCategoryTransfer.getInstance(), ProposalListTransfer.getInstance() };
111
		DropTarget dropTarget= new DropTarget(composite, ProposalTransfer.ALL_DRAG_OPERATIONS);
112
		dropTarget.setTransfer(transferTypes);
113
		dropTarget.addDropListener(new AutoscrollDropTargetListener(this));
114
	}
115
116
	private Composite createInnerProposalListWrappingComposite(ScrolledComposite scrolledComposite) {
117
		Composite wrappingComposite= new Composite(scrolledComposite, SWT.NONE);
118
		scrolledComposite.setContent(wrappingComposite);
119
		GridLayout layout= new GridLayout();
120
		layout.marginHeight= 0;
121
		layout.verticalSpacing= 0;
122
		wrappingComposite.setLayout(layout);
123
		return wrappingComposite;
124
	}
125
126
	private void addOuterSizeUpdater(final ScrolledComposite scrolledComposite, final Composite innerComposite) {
127
		innerComposite.addControlListener(new ControlListener() {
128
			public void controlResized(ControlEvent e) {
129
				innerComposite.update();
130
				scrolledComposite.setMinSize(innerComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
131
				scrolledComposite.layout(true, true);
132
			}
133
134
			public void controlMoved(ControlEvent e) {
135
			}
136
		});
137
	}
138
139
	private void createFirstNewListDropSection(Composite innerWrappingComposite) {
140
		new NewListDropSection(innerWrappingComposite, 0, fModel, this, fUtilitiesProxy);
141
	}
142
143
	private void clearOldListState() {
144
		for (ProposalList list : fProposalLists)
145
			list.clearContent();
146
	}
147
148
	private Set<Integer> updateListStates() {
149
		Set<Integer> filledLists= new HashSet<Integer>();
150
		for (ModelElement element : fModel.elements) {
151
			Set<Integer> indices= element.getProposalListIndices();
152
			if (indices != null) {
153
				filledLists.addAll(indices);
154
				for (int index : indices) {
155
					makeSureListExists(index);
156
					addElementToList(element, index);
157
				}
158
			}
159
		}
160
		return filledLists;
161
	}
162
163
	private void makeSureFirstListExists() {
164
		if (fProposalLists.size() == 0)
165
			makeSureListExists(0);
166
	}
167
168
	private void adjustAndCleanUp(Set<Integer> filledLists) {
169
		boolean last= true;
170
		for (int i= fProposalLists.size() - 1; i >= 0; i--)
171
			if (i > 0 && !filledLists.contains(Integer.valueOf(i))) {
172
				fProposalLists.get(i).dispose();
173
				fProposalLists.remove(i);
174
			}
175
			else {
176
				fProposalLists.get(i).activateLastListSpaceBehavior(last);
177
				last= false;
178
			}
179
	}
180
181
	private void reLayoutInnerComposite() {
182
		fInnerWrappingComposite.pack(true);
183
		fInnerWrappingComposite.layout(false);
184
	}
185
186
	private void addElementToList(ModelElement element, int listIndex) {
187
		fProposalLists.get(listIndex).addContent(element);
188
	}
189
190
	private void makeSureListExists(int listIndex) {
191
		while (fProposalLists.size() < listIndex + 1)
192
			fProposalLists.add(new ProposalList(fInnerWrappingComposite, fProposalLists.size(), this, fModel, fUtilitiesProxy));
193
	}
194
}
(-)ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java (-34 / +43 lines)
Lines 7-19 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.text.java;
12
package org.eclipse.jdt.internal.ui.text.java;
12
13
13
import java.net.URL;
14
import java.net.URL;
14
import java.util.ArrayList;
15
import java.util.ArrayList;
16
import java.util.Collection;
17
import java.util.Collections;
18
import java.util.HashSet;
15
import java.util.Iterator;
19
import java.util.Iterator;
16
import java.util.List;
20
import java.util.List;
21
import java.util.Set;
17
22
18
import org.osgi.framework.Bundle;
23
import org.osgi.framework.Bundle;
19
24
Lines 55-66 Link Here
55
	/** The image descriptor for this category, or <code>null</code> if none specified. */
60
	/** The image descriptor for this category, or <code>null</code> if none specified. */
56
	private final ImageDescriptor fImage;
61
	private final ImageDescriptor fImage;
57
62
58
	private boolean fIsSeparateCommand= true;
63
	private final Set<Integer> fProposalListIndices = new HashSet<Integer>();
64
	private final Set<Integer> fPublicProposalListIndices= Collections.unmodifiableSet(fProposalListIndices);
59
	private boolean fIsEnabled= true;
65
	private boolean fIsEnabled= true;
60
	private boolean fIsIncluded= true;
61
	private final CompletionProposalComputerRegistry fRegistry;
66
	private final CompletionProposalComputerRegistry fRegistry;
62
67
63
	private int fSortOrder= 0xffff - 1;
64
	private String fLastError= null;
68
	private String fLastError= null;
65
69
66
	CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) throws CoreException {
70
	CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) throws CoreException {
Lines 158-192 Link Here
158
	}
162
	}
159
163
160
	/**
164
	/**
161
	 * Sets the separate command state of the category.
165
	 * Adds the given proposal list index to the proposal list indices of this category.
162
	 *
166
	 * 
163
	 * @param enabled the new enabled state.
167
	 * @param listIndex the index of the proposal list.
164
	 */
168
	 */
165
	public void setSeparateCommand(boolean enabled) {
169
	public void addProposalListIndex(Integer listIndex) {
166
		fIsSeparateCommand= enabled;
170
		fProposalListIndices.add(listIndex);
167
	}
171
	}
168
172
169
	/**
173
	/**
170
	 * Returns the enablement state of the category.
174
	 * Adds all given proposal list indices to the proposal list indices of this category.
171
	 *
175
	 * 
172
	 * @return the enablement state of the category
176
	 * @param listIndices the indices of the proposal lists.
173
	 */
177
	 */
174
	public boolean isSeparateCommand() {
178
	public void addAllProposalListIndices(Collection<Integer> listIndices) {
175
		return fIsSeparateCommand;
179
		if (listIndices == null)
180
			return;
181
		fProposalListIndices.addAll(listIndices);
176
	}
182
	}
177
183
178
	/**
184
	/**
179
	 * @param included the included
185
	 * Removes all given proposal list indices from the proposal list indices of this category.
186
	 * 
187
	 * @param listIndices the indices of the proposal lists.
180
	 */
188
	 */
181
	public void setIncluded(boolean included) {
189
	public void removeAllProposalListIndices(Collection<Integer> listIndices) {
182
		fIsIncluded= included;
190
		if (listIndices == null)
191
			return;
192
		fProposalListIndices.removeAll(listIndices);
183
	}
193
	}
184
194
185
	/**
195
	/**
186
	 * @return included
196
	 * Clears the list of proposal list indices of this category.
197
	 * 
187
	 */
198
	 */
188
	public boolean isIncluded() {
199
	public void clearProposalListIndices() {
189
		return fIsIncluded;
200
		fProposalListIndices.clear();
201
	}
202
203
	/**
204
	 * Returns the indices of the proposal lists of this category.
205
	 * <p>
206
	 * The returned set is read-only.
207
	 * </p>
208
	 * 
209
	 * @return the indices of the proposal lists of this category
210
	 */
211
	public Set<Integer> getProposalListIndices() {
212
		return fPublicProposalListIndices;
190
	}
213
	}
191
214
192
	public boolean isEnabled() {
215
	public boolean isEnabled() {
Lines 233-252 Link Here
233
	}
256
	}
234
257
235
	/**
258
	/**
236
	 * @return sortOrder
237
	 */
238
	public int getSortOrder() {
239
		return fSortOrder;
240
	}
241
242
	/**
243
	 * @param sortOrder the sortOrder
244
	 */
245
	public void setSortOrder(int sortOrder) {
246
		fSortOrder= sortOrder;
247
	}
248
249
	/**
250
	 * Safely computes completion proposals of all computers of this category through their
259
	 * Safely computes completion proposals of all computers of this category through their
251
	 * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
260
	 * extension. If an extension is disabled, throws an exception or otherwise does not adhere to
252
	 * the contract described in {@link IJavaCompletionProposalComputer}, it is disabled.
261
	 * the contract described in {@link IJavaCompletionProposalComputer}, it is disabled.
Lines 288-294 Link Here
288
		List<CompletionProposalComputerDescriptor> descriptors= new ArrayList<CompletionProposalComputerDescriptor>(fRegistry.getProposalComputerDescriptors(partition));
297
		List<CompletionProposalComputerDescriptor> descriptors= new ArrayList<CompletionProposalComputerDescriptor>(fRegistry.getProposalComputerDescriptors(partition));
289
		for (Iterator<CompletionProposalComputerDescriptor> it= descriptors.iterator(); it.hasNext();) {
298
		for (Iterator<CompletionProposalComputerDescriptor> it= descriptors.iterator(); it.hasNext();) {
290
			CompletionProposalComputerDescriptor desc= it.next();
299
			CompletionProposalComputerDescriptor desc= it.next();
291
			if (desc.getCategory() == this && (isIncluded() || isSeparateCommand()))
300
			if (desc.getCategory() == this && !fProposalListIndices.isEmpty())
292
				result.addAll(desc.computeContextInformation(context, monitor));
301
				result.addAll(desc.computeContextInformation(context, monitor));
293
			if (fLastError == null)
302
			if (fLastError == null)
294
				fLastError= desc.getErrorMessage();
303
				fLastError= desc.getErrorMessage();
(-)ui/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerRegistry.java (-40 / +49 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.text.java;
12
package org.eclipse.jdt.internal.ui.text.java;
12
13
Lines 21-26 Link Here
21
import java.util.Map;
22
import java.util.Map;
22
import java.util.Set;
23
import java.util.Set;
23
import java.util.StringTokenizer;
24
import java.util.StringTokenizer;
25
import java.util.TreeMap;
26
import java.util.Map.Entry;
24
27
25
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.events.SelectionAdapter;
29
import org.eclipse.swt.events.SelectionAdapter;
Lines 330-354 Link Here
330
333
331
	private List<CompletionProposalCategory> getCategories(List<IConfigurationElement> elements) {
334
	private List<CompletionProposalCategory> getCategories(List<IConfigurationElement> elements) {
332
		IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
335
		IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
333
		String preference= store.getString(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
336
		String preference= store.getString(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS);
334
		Set<String> disabled= new HashSet<String>();
337
		Map<String, Set<Integer>> proposalLists= new HashMap<String, Set<Integer>>();
335
		StringTokenizer tok= new StringTokenizer(preference, "\0");  //$NON-NLS-1$
338
		StringTokenizer tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$
336
		while (tok.hasMoreTokens())
339
		for (int i= 0; tok.hasMoreTokens(); i++) {
337
			disabled.add(tok.nextToken());
338
		Map<String, Integer> ordered= new HashMap<String, Integer>();
339
		preference= store.getString(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
340
		tok= new StringTokenizer(preference, "\0"); //$NON-NLS-1$
341
		while (tok.hasMoreTokens()) {
342
			StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$
340
			StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$
343
			String id= inner.nextToken();
341
			if (inner.countTokens() == 0)
344
			int rank= Integer.parseInt(inner.nextToken());
342
				i--;
345
			ordered.put(id, new Integer(rank));
343
			while (inner.hasMoreTokens()) {
344
				String categoryId= inner.nextToken();
345
				Set<Integer> set= proposalLists.get(categoryId);
346
				if (set == null) {
347
					set= new HashSet<Integer>();
348
					proposalLists.put(categoryId, set);
349
				}
350
				set.add(Integer.valueOf(i));
351
			}
346
		}
352
		}
347
353
348
		CompletionProposalCategory allProposals= null;
354
		CompletionProposalCategory allProposals= null;
349
		CompletionProposalCategory typeProposals= null;
355
		CompletionProposalCategory typeProposals= null;
350
		CompletionProposalCategory allButTypeProposals= null;
356
		CompletionProposalCategory allButTypeProposals= null;
351
		
357
352
		List<CompletionProposalCategory> categories= new ArrayList<CompletionProposalCategory>();
358
		List<CompletionProposalCategory> categories= new ArrayList<CompletionProposalCategory>();
353
		for (Iterator<IConfigurationElement> iter= elements.iterator(); iter.hasNext();) {
359
		for (Iterator<IConfigurationElement> iter= elements.iterator(); iter.hasNext();) {
354
			IConfigurationElement element= iter.next();
360
			IConfigurationElement element= iter.next();
Lines 358-374 Link Here
358
364
359
					CompletionProposalCategory category= new CompletionProposalCategory(element, this);
365
					CompletionProposalCategory category= new CompletionProposalCategory(element, this);
360
					categories.add(category);
366
					categories.add(category);
361
					category.setIncluded(!disabled.contains(category.getId()));
367
					category.addAllProposalListIndices(proposalLists.get(category.getId()));
362
					Integer rank= ordered.get(category.getId());
368
363
					if (rank != null) {
364
						int r= rank.intValue();
365
						boolean separate= r < 0xffff;
366
						if (!separate)
367
							r= r - 0xffff;
368
						category.setSeparateCommand(separate);
369
						category.setSortOrder(r);
370
					}
371
					
372
					String id= category.getId();
369
					String id= category.getId();
373
					if ("org.eclipse.jdt.ui.javaAllProposalCategory".equals(id)) //$NON-NLS-1$
370
					if ("org.eclipse.jdt.ui.javaAllProposalCategory".equals(id)) //$NON-NLS-1$
374
						allProposals= category;
371
						allProposals= category;
Lines 383-389 Link Here
383
				 * some other reason. Do not include the extension in the list and inform the user
380
				 * some other reason. Do not include the extension in the list and inform the user
384
				 * about it.
381
				 * about it.
385
				 */
382
				 */
386
				Object[] args= {element.toString()};
383
				Object[] args= { element.toString() };
387
				String message= Messages.format(JavaTextMessages.CompletionProposalComputerRegistry_invalid_message, args);
384
				String message= Messages.format(JavaTextMessages.CompletionProposalComputerRegistry_invalid_message, args);
388
				IStatus status= new Status(IStatus.WARNING, JavaPlugin.getPluginId(), IStatus.OK, message, x);
385
				IStatus status= new Status(IStatus.WARNING, JavaPlugin.getPluginId(), IStatus.OK, message, x);
389
				informUser(status);
386
				informUser(status);
Lines 391-425 Link Here
391
				informUser(x.getStatus());
388
				informUser(x.getStatus());
392
			}
389
			}
393
		}
390
		}
394
		preventDuplicateCategories(store, disabled, allProposals, typeProposals, allButTypeProposals);
391
		preventDuplicateCategories(store, proposalLists, allProposals, typeProposals, allButTypeProposals, categories.size());
395
		return categories;
392
		return categories;
396
	}
393
	}
397
394
398
	private void preventDuplicateCategories(IPreferenceStore store, Set<String> disabled, CompletionProposalCategory allProposals, CompletionProposalCategory typeProposals,
395
	private void preventDuplicateCategories(IPreferenceStore store, Map<String, Set<Integer>> proposalLists, CompletionProposalCategory allProposals, CompletionProposalCategory typeProposals,
399
			CompletionProposalCategory allButTypeProposals) {
396
			CompletionProposalCategory allButTypeProposals, int numberOfCategories) {
400
		boolean adjusted= false;
397
		boolean adjusted= false;
401
		if (allProposals == null || !allProposals.isIncluded())
398
		if (allProposals == null || allProposals.getProposalListIndices().isEmpty())
402
			return;
399
			return;
403
400
404
		if (allButTypeProposals != null && allButTypeProposals.isIncluded()) {
401
		if (allButTypeProposals != null && !allButTypeProposals.getProposalListIndices().isEmpty()) {
405
			allButTypeProposals.setIncluded(false);
402
			allButTypeProposals.removeAllProposalListIndices(allProposals.getProposalListIndices());
406
			disabled.add(allButTypeProposals.getId());
403
			proposalLists.put(allButTypeProposals.getId(), allButTypeProposals.getProposalListIndices());
407
			adjusted= true;
404
			adjusted= true;
408
		}
405
		}
409
		if (typeProposals != null && typeProposals.isIncluded()) {
406
		if (typeProposals != null && !typeProposals.getProposalListIndices().isEmpty()) {
410
			typeProposals.setIncluded(false);
407
			typeProposals.removeAllProposalListIndices(allProposals.getProposalListIndices());
411
			disabled.add(typeProposals.getId());
408
			proposalLists.put(typeProposals.getId(), typeProposals.getProposalListIndices());
412
			adjusted= true;
409
			adjusted= true;
413
		}
410
		}
414
411
415
		if (adjusted) {
412
		if (adjusted) {
416
			StringBuffer buf= new StringBuffer(50 * disabled.size());
413
			int initialBufferSize= 50 * numberOfCategories;
417
			Iterator<String> iter= disabled.iterator();
414
			Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
418
			while (iter.hasNext()) {
415
			for (Entry<String, Set<Integer>> category : proposalLists.entrySet()) {
419
				buf.append(iter.next());
416
				for (Integer index : category.getValue()) {
417
					StringBuffer buf= proposalListsCategories.get(index);
418
					if (buf == null) {
419
						buf= new StringBuffer(initialBufferSize);
420
						proposalListsCategories.put(index, buf);
421
					}
422
					buf.append(category.getKey());
423
					buf.append(':');
424
				}
425
			}
426
			StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size());
427
			for (StringBuffer proposalList : proposalListsCategories.values()) {
428
				buf.append(proposalList);
420
				buf.append('\0');
429
				buf.append('\0');
421
			}
430
			}
422
			store.putValue(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES, buf.toString());
431
			store.putValue(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS, buf.toString());
423
		}
432
		}
424
	}
433
	}
425
434
(-)ui/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java (-61 / +33 lines)
Lines 7-20 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.text.java;
12
package org.eclipse.jdt.internal.ui.text.java;
12
13
13
import java.util.ArrayList;
14
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.Iterator;
15
import java.util.Iterator;
17
import java.util.List;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.TreeMap;
18
19
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.events.SelectionAdapter;
21
import org.eclipse.swt.events.SelectionAdapter;
Lines 186-199 Link Here
186
	 */
187
	 */
187
	private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; //$NON-NLS-1$
188
	private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; //$NON-NLS-1$
188
189
189
	private static final Comparator<CompletionProposalCategory> ORDER_COMPARATOR= new Comparator<CompletionProposalCategory>() {
190
191
		public int compare(CompletionProposalCategory d1, CompletionProposalCategory d2) {
192
			return d1.getSortOrder() - d2.getSortOrder();
193
		}
194
195
	};
196
197
	private final List<CompletionProposalCategory> fCategories;
190
	private final List<CompletionProposalCategory> fCategories;
198
	private final String fPartition;
191
	private final String fPartition;
199
	private final ContentAssistant fAssistant;
192
	private final ContentAssistant fAssistant;
Lines 444-490 Link Here
444
	}
437
	}
445
438
446
	private List<List<CompletionProposalCategory>> getCategoryIteration() {
439
	private List<List<CompletionProposalCategory>> getCategoryIteration() {
447
		List<List<CompletionProposalCategory>> sequence= new ArrayList<List<CompletionProposalCategory>>();
440
		List<List<CompletionProposalCategory>> categories= getProposalCategoriesUnchecked();
448
		sequence.add(getDefaultCategories());
441
		if (fComputerRegistry.hasUninstalledComputers(fPartition, categories.get(0))) {
449
		for (Iterator<CompletionProposalCategory> it= getSeparateCategories().iterator(); it.hasNext();) {
442
			if (informUserAboutEmptyFirstProposalCategory())
450
			CompletionProposalCategory cat= it.next();
443
				// preferences were restored - recompute the categories in the first proposal list
451
			sequence.add(Collections.singletonList(cat));
444
				categories= getProposalCategoriesUnchecked();
452
		}
453
		return sequence;
454
	}
455
456
	private List<CompletionProposalCategory> getDefaultCategories() {
457
		// default mix - enable all included computers
458
		List<CompletionProposalCategory> included= getDefaultCategoriesUnchecked();
459
460
		if (fComputerRegistry.hasUninstalledComputers(fPartition, included)) {
461
			if (informUserAboutEmptyDefaultCategory())
462
				// preferences were restored - recompute the default categories
463
				included= getDefaultCategoriesUnchecked();
464
			fComputerRegistry.resetUnistalledComputers();
445
			fComputerRegistry.resetUnistalledComputers();
465
		}
446
		}
466
447
		return categories;
467
		return included;
468
	}
448
	}
469
449
470
	private List<CompletionProposalCategory> getDefaultCategoriesUnchecked() {
450
	private List<List<CompletionProposalCategory>> getProposalCategoriesUnchecked() {
471
		List<CompletionProposalCategory> included= new ArrayList<CompletionProposalCategory>();
451
		Map<Integer, List<CompletionProposalCategory>> sorted= new TreeMap<Integer, List<CompletionProposalCategory>>();
472
		for (Iterator<CompletionProposalCategory> it= fCategories.iterator(); it.hasNext();) {
452
		for (CompletionProposalCategory category : fCategories) {
473
			CompletionProposalCategory category= it.next();
453
			if (!category.getProposalListIndices().isEmpty() && category.hasComputers(fPartition)) {
474
			if (category.isIncluded() && category.hasComputers(fPartition))
454
				for (Integer index : category.getProposalListIndices()) {
475
				included.add(category);
455
					List<CompletionProposalCategory> list= sorted.get(index);
456
					if (list == null) {
457
						list= new ArrayList<CompletionProposalCategory>();
458
						sorted.put(index, list);
459
					}
460
					list.add(category);
461
				}
462
			}
476
		}
463
		}
477
		return included;
464
		// put at least an empty first list
465
		if (sorted.isEmpty())
466
			sorted.put(Integer.valueOf(0), new ArrayList<CompletionProposalCategory>());
467
		return new ArrayList<List<CompletionProposalCategory>>(sorted.values());
478
	}
468
	}
479
469
480
	/**
470
	/**
481
	 * Informs the user about the fact that there are no enabled categories in the default content
471
	 * Informs the user about the fact that there are no enabled categories in the first content
482
	 * assist set and shows a link to the preferences.
472
	 * assist proposal list set and shows a link to the preferences.
483
	 *
473
	 * 
484
	 * @return  <code>true</code> if the default should be restored
474
	 * @return <code>true</code> if the default should be restored
485
	 * @since 3.3
475
	 * @since 3.3
486
	 */
476
	 */
487
	private boolean informUserAboutEmptyDefaultCategory() {
477
	private boolean informUserAboutEmptyFirstProposalCategory() {
488
		if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) {
478
		if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) {
489
			final Shell shell= JavaPlugin.getActiveWorkbenchShell();
479
			final Shell shell= JavaPlugin.getActiveWorkbenchShell();
490
			String title= JavaTextMessages.ContentAssistProcessor_all_disabled_title;
480
			String title= JavaTextMessages.ContentAssistProcessor_all_disabled_title;
Lines 549-556 Link Here
549
	        if (restoreId == returnValue || settingsId == returnValue) {
539
	        if (restoreId == returnValue || settingsId == returnValue) {
550
	        	if (restoreId == returnValue) {
540
	        	if (restoreId == returnValue) {
551
	        		IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
541
	        		IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
552
	        		store.setToDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER);
542
					store.setToDefault(PreferenceConstants.CODEASSIST_PROPOSAL_LISTS);
553
	        		store.setToDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES);
554
	        	}
543
	        	}
555
	        	if (settingsId == returnValue)
544
	        	if (settingsId == returnValue)
556
					PreferencesUtil.createPreferenceDialogOn(shell, "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$
545
					PreferencesUtil.createPreferenceDialogOn(shell, "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); //$NON-NLS-1$
Lines 561-577 Link Here
561
		return false;
550
		return false;
562
	}
551
	}
563
552
564
	private List<CompletionProposalCategory> getSeparateCategories() {
565
		ArrayList<CompletionProposalCategory> sorted= new ArrayList<CompletionProposalCategory>();
566
		for (Iterator<CompletionProposalCategory> it= fCategories.iterator(); it.hasNext();) {
567
			CompletionProposalCategory category= it.next();
568
			if (category.isSeparateCommand() && category.hasComputers(fPartition))
569
				sorted.add(category);
570
		}
571
		Collections.sort(sorted, ORDER_COMPARATOR);
572
		return sorted;
573
	}
574
575
	private String createEmptyMessage() {
553
	private String createEmptyMessage() {
576
		return Messages.format(JavaTextMessages.ContentAssistProcessor_empty_message, new String[]{getCategoryLabel(fRepetition)});
554
		return Messages.format(JavaTextMessages.ContentAssistProcessor_empty_message, new String[]{getCategoryLabel(fRepetition)});
577
	}
555
	}
Lines 582-594 Link Here
582
560
583
	private String getCategoryLabel(int repetition) {
561
	private String getCategoryLabel(int repetition) {
584
		int iteration= repetition % fCategoryIteration.size();
562
		int iteration= repetition % fCategoryIteration.size();
585
		if (iteration == 0)
563
		return Messages.format(JavaTextMessages.ContentAssistProcessor_proposalList, Integer.valueOf(iteration + 1));
586
			return JavaTextMessages.ContentAssistProcessor_defaultProposalCategory;
587
		return toString(fCategoryIteration.get(iteration).get(0));
588
	}
589
590
	private String toString(CompletionProposalCategory category) {
591
		return category.getDisplayName();
592
	}
564
	}
593
565
594
	private String getIterationGesture() {
566
	private String getIterationGesture() {
(-)ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java (-1 / +2 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.jdt.internal.ui.text.java;
12
package org.eclipse.jdt.internal.ui.text.java;
12
13
Lines 59-65 Link Here
59
	public static String CompletionProposalComputerDescriptor_blame_message;
60
	public static String CompletionProposalComputerDescriptor_blame_message;
60
	public static String CompletionProposalComputerRegistry_invalid_message;
61
	public static String CompletionProposalComputerRegistry_invalid_message;
61
	public static String CompletionProposalComputerRegistry_error_dialog_title;
62
	public static String CompletionProposalComputerRegistry_error_dialog_title;
62
	public static String ContentAssistProcessor_defaultProposalCategory;
63
	public static String ContentAssistProcessor_proposalList;
63
	public static String ContentAssistProcessor_toggle_affordance_press_gesture;
64
	public static String ContentAssistProcessor_toggle_affordance_press_gesture;
64
	public static String ContentAssistProcessor_toggle_affordance_click_gesture;
65
	public static String ContentAssistProcessor_toggle_affordance_click_gesture;
65
	public static String ContentAssistProcessor_toggle_affordance_update_message;
66
	public static String ContentAssistProcessor_toggle_affordance_update_message;
(-)ui/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.properties (-2 / +3 lines)
Lines 7-12 Link Here
7
#
7
#
8
# Contributors:
8
# Contributors:
9
#     IBM Corporation - initial API and implementation
9
#     IBM Corporation - initial API and implementation
10
#     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
10
###############################################################################
11
###############################################################################
11
12
12
CompletionProcessor_error_accessing_title=Error Accessing Compilation Unit
13
CompletionProcessor_error_accessing_title=Error Accessing Compilation Unit
Lines 57-70 Link Here
57
ContentAssistProcessor_all_disabled_preference_link=Change the settings on the <a>Advanced Content Assist preference page</a> or click ''{0}'' to restore the default behavior.
58
ContentAssistProcessor_all_disabled_preference_link=Change the settings on the <a>Advanced Content Assist preference page</a> or click ''{0}'' to restore the default behavior.
58
ContentAssistProcessor_collecting_contexts=Collecting context information
59
ContentAssistProcessor_collecting_contexts=Collecting context information
59
ContentAssistProcessor_sorting_contexts=Sorting
60
ContentAssistProcessor_sorting_contexts=Sorting
60
ContentAssistProcessor_defaultProposalCategory=Default Proposals
61
ContentAssistProcessor_proposalList={0}. Proposal List
61
# {0} will be replaced by a keyboard shortcut (accelerator)
62
# {0} will be replaced by a keyboard shortcut (accelerator)
62
ContentAssistProcessor_toggle_affordance_press_gesture=Press ''{0}''
63
ContentAssistProcessor_toggle_affordance_press_gesture=Press ''{0}''
63
ContentAssistProcessor_toggle_affordance_click_gesture=Click
64
ContentAssistProcessor_toggle_affordance_click_gesture=Click
64
# {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 
65
# {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 
65
ContentAssistProcessor_toggle_affordance_update_message={1} to show {2}
66
ContentAssistProcessor_toggle_affordance_update_message={1} to show {2}
66
# {0} will be replaced by a title describing the displayed proposal category
67
# {0} will be replaced by a title describing the displayed proposal category
67
ContentAssistProcessor_empty_message= No {0}
68
ContentAssistProcessor_empty_message= No proposals in {0}
68
69
69
ContentAssistHistory_serialize_error=Problems writing content assist history to XML
70
ContentAssistHistory_serialize_error=Problems writing content assist history to XML
70
ContentAssistHistory_deserialize_error=Problems reading content assist history from XML
71
ContentAssistHistory_deserialize_error=Problems reading content assist history from XML
(-)ui/org/eclipse/jdt/ui/PreferenceConstants.java (-31 / +76 lines)
Lines 8-19 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
10
 *     Guven Demir <guven.internet+eclipse@gmail.com> - [package explorer] Alternative package name shortening: abbreviation - https://bugs.eclipse.org/bugs/show_bug.cgi?id=299514
11
 *     Thomas Schlosser <schlosser@stud.tu-darmstadt.de> - 340876 [preferences][content assist] Request for more flexible configuration of content assist lists - https://bugs.eclipse.org/bugs/show_bug.cgi?id=340876
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.jdt.ui;
13
package org.eclipse.jdt.ui;
13
14
14
import java.util.Arrays;
15
import java.util.Arrays;
15
import java.util.Locale;
16
import java.util.Locale;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.Map.Entry;
20
import java.util.Map;
21
import java.util.Set;
16
import java.util.StringTokenizer;
22
import java.util.StringTokenizer;
23
import java.util.TreeMap;
17
24
18
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.graphics.RGB;
26
import org.eclipse.swt.graphics.RGB;
Lines 3174-3182 Link Here
3174
	 * Value is of type <code>String</code>, a "\0"-separated list of identifiers.
3181
	 * Value is of type <code>String</code>, a "\0"-separated list of identifiers.
3175
	 * </p>
3182
	 * </p>
3176
	 *
3183
	 *
3177
	 * @see #getExcludedCompletionProposalCategories()
3178
	 * @see #setExcludedCompletionProposalCategories(String[])
3179
	 * @since 3.2
3184
	 * @since 3.2
3185
	 * @deprecated As of 3.8, use {@link #CODEASSIST_PROPOSAL_LISTS} instead
3180
	 */
3186
	 */
3181
	public static final String CODEASSIST_EXCLUDED_CATEGORIES= "content_assist_disabled_computers"; //$NON-NLS-1$
3187
	public static final String CODEASSIST_EXCLUDED_CATEGORIES= "content_assist_disabled_computers"; //$NON-NLS-1$
3182
3188
Lines 3196-3203 Link Here
3196
	 * </p>
3202
	 * </p>
3197
	 * 
3203
	 * 
3198
	 * @since 3.2
3204
	 * @since 3.2
3205
	 * @deprecated As of 3.8, use {@link #CODEASSIST_PROPOSAL_LISTS} instead
3199
	 */
3206
	 */
3200
	public static final String CODEASSIST_CATEGORY_ORDER= "content_assist_category_order"; //$NON-NLS-1$
3207
	public static final String CODEASSIST_CATEGORY_ORDER= "content_assist_category_order"; //$NON-NLS-1$
3208
	
3209
	/**
3210
	 * A named preference that controls which completion proposal category is included in which proposal list.
3211
	 * <p>
3212
	 * Value is of type <code>String</code>, a "\0"-separated list of "\1"-separated lists with categoryId where
3213
	 * <ul>
3214
	 * <li>categoryId is the <code>String</code> holding the category ID</li>
3215
	 * </ul>
3216
	 * 
3217
	 * </p>
3218
	 * 
3219
	 * @see #getProposalLists()
3220
	 * @see #setProposalLists(Map)
3221
	 * @since 3.8
3222
	 */
3223
	public static final String CODEASSIST_PROPOSAL_LISTS= "content_assist_proposal_lists"; //$NON-NLS-1$
3201
3224
3202
	/**
3225
	/**
3203
	 * A named preference that controls whether folding is enabled in the Java editor.
3226
	 * A named preference that controls whether folding is enabled in the Java editor.
Lines 3784-3791 Link Here
3784
		store.setDefault(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, true);
3807
		store.setDefault(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES, true);
3785
		store.setDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, false);
3808
		store.setDefault(PreferenceConstants.CODEASSIST_GUESS_METHOD_ARGUMENTS, false);
3786
		store.setDefault(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION, false);
3809
		store.setDefault(PreferenceConstants.CODEASSIST_PREFIX_COMPLETION, false);
3787
		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$
3810
		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$
3788
		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$
3789
		store.setDefault(PreferenceConstants.CODEASSIST_LRU_HISTORY, ""); //$NON-NLS-1$
3811
		store.setDefault(PreferenceConstants.CODEASSIST_LRU_HISTORY, ""); //$NON-NLS-1$
3790
		store.setDefault(PreferenceConstants.CODEASSIST_SORTER, "org.eclipse.jdt.ui.RelevanceSorter"); //$NON-NLS-1$
3812
		store.setDefault(PreferenceConstants.CODEASSIST_SORTER, "org.eclipse.jdt.ui.RelevanceSorter"); //$NON-NLS-1$
3791
		store.setDefault(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, ""); //$NON-NLS-1$
3813
		store.setDefault(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, ""); //$NON-NLS-1$
Lines 4005-4042 Link Here
4005
	}
4027
	}
4006
4028
4007
	/**
4029
	/**
4008
	 * Returns the completion proposal categories which
4030
	 * Returns the completion proposal categories with their corresponding proposal list indices.
4009
	 * are excluded from the default proposal list.
4031
	 * 
4010
	 *
4032
	 * @return a map which maps the category IDs to a set of proposal list indices
4011
	 * @return an array with the IDs of the excluded categories
4033
	 * @see #CODEASSIST_PROPOSAL_LISTS
4012
	 * @see #CODEASSIST_EXCLUDED_CATEGORIES
4034
	 * @since 3.8
4013
	 * @since 3.4
4035
	 */
4014
	 */
4036
	public static Map<String, Set<Integer>> getProposalLists() {
4015
	public static String[] getExcludedCompletionProposalCategories() {
4037
		String encodedPreference= getPreference(CODEASSIST_PROPOSAL_LISTS, null);
4016
		String encodedPreference= getPreference(CODEASSIST_EXCLUDED_CATEGORIES, null);
4038
		Map<String, Set<Integer>> result= new HashMap<String, Set<Integer>>();
4017
		StringTokenizer tokenizer= new StringTokenizer(encodedPreference, "\0"); //$NON-NLS-1$
4039
		StringTokenizer tok= new StringTokenizer(encodedPreference, "\0"); //$NON-NLS-1$
4018
		String[] result= new String[tokenizer.countTokens()];
4040
		for (int i= 0; tok.hasMoreTokens(); i++) {
4019
		for (int i= 0; i < result.length; i++)
4041
			StringTokenizer inner= new StringTokenizer(tok.nextToken(), ":"); //$NON-NLS-1$
4020
			result[i]= tokenizer.nextToken();
4042
			if (inner.countTokens() == 0)
4043
				i--;
4044
			while (inner.hasMoreTokens()) {
4045
				String category= inner.nextToken();
4046
				Set<Integer> set= result.get(category);
4047
				if (set == null) {
4048
					set= new HashSet<Integer>();
4049
					result.put(category, set);
4050
				}
4051
				set.add(Integer.valueOf(i));
4052
			}
4053
		}
4021
		return result;
4054
		return result;
4022
	}
4055
	}
4023
4056
4024
	/**
4057
	/**
4025
	 * Sets the completion proposal categories which are excluded from the
4058
	 * Sets the completion proposal categories for each proposal list and reloads the registry.
4026
	 * default proposal list and reloads the registry.
4059
	 * 
4027
	 *
4060
	 * @param proposalLists a map which maps the category IDs to a set of proposal list indices
4028
	 * @param categories the array with the IDs of the excluded categories
4061
	 * @see #CODEASSIST_PROPOSAL_LISTS
4029
	 * @see #CODEASSIST_EXCLUDED_CATEGORIES
4062
	 * @since 3.8
4030
	 * @since 3.4
4063
	 */
4031
	 */
4064
	public static void setProposalLists(Map<String, Set<Integer>> proposalLists) {
4032
	public static void setExcludedCompletionProposalCategories(String[] categories) {
4065
		Assert.isLegal(proposalLists != null);
4033
		Assert.isLegal(categories != null);
4066
		int initialBufferSize= 250;
4034
		StringBuffer buf= new StringBuffer(50 * categories.length);
4067
		Map<Integer, StringBuffer> proposalListsCategories= new TreeMap<Integer, StringBuffer>();
4035
		for (int i= 0; i < categories.length; i++) {
4068
		for (Entry<String, Set<Integer>> category : proposalLists.entrySet()) {
4036
			buf.append(categories[i]);
4069
			for (Integer index : category.getValue()) {
4037
			buf.append('\0');
4070
				StringBuffer buf= proposalListsCategories.get(index);
4071
				if (buf == null) {
4072
					buf= new StringBuffer(initialBufferSize);
4073
					proposalListsCategories.put(index, buf);
4074
				}
4075
				buf.append(category.getKey());
4076
				buf.append(":"); //$NON-NLS-1$
4077
			}
4078
		}
4079
		StringBuffer buf= new StringBuffer(initialBufferSize * proposalListsCategories.size());
4080
		for (StringBuffer proposalList : proposalListsCategories.values()) {
4081
			buf.append(proposalList);
4082
			buf.append("\0"); //$NON-NLS-1$
4038
		}
4083
		}
4039
		getPreferenceStore().setValue(CODEASSIST_EXCLUDED_CATEGORIES, buf.toString());
4084
		getPreferenceStore().setValue(CODEASSIST_PROPOSAL_LISTS, buf.toString());
4040
		CompletionProposalComputerRegistry.getDefault().reload();
4085
		CompletionProposalComputerRegistry.getDefault().reload();
4041
	}
4086
	}
4042
4087

Return to bug 340876