blob: e1cfeadda06eaaa2e46b04e136e10488b8986353 [file] [log] [blame]
nsandonato3b334302010-02-26 20:59:38 +00001/*******************************************************************************
2 * Copyright (c) 2010 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 *******************************************************************************/
11package org.eclipse.wst.sse.ui.preferences;
12
13import java.util.ArrayList;
14import java.util.Collections;
15import java.util.Comparator;
16import java.util.HashMap;
17import java.util.Iterator;
18import java.util.List;
19import java.util.Map;
20
21import org.eclipse.core.commands.Command;
22import org.eclipse.core.commands.CommandManager;
23import org.eclipse.core.commands.ParameterizedCommand;
24import org.eclipse.core.commands.common.NotDefinedException;
25import org.eclipse.core.commands.contexts.ContextManager;
26import org.eclipse.core.runtime.Assert;
27import org.eclipse.jface.bindings.BindingManager;
28import org.eclipse.jface.bindings.Scheme;
29import org.eclipse.jface.bindings.TriggerSequence;
30import org.eclipse.jface.layout.PixelConverter;
31import org.eclipse.jface.resource.ImageDescriptor;
32import org.eclipse.jface.resource.JFaceResources;
33import org.eclipse.jface.viewers.ArrayContentProvider;
34import org.eclipse.jface.viewers.CheckStateChangedEvent;
35import org.eclipse.jface.viewers.CheckboxTableViewer;
36import org.eclipse.jface.viewers.ICheckStateListener;
37import org.eclipse.jface.viewers.IStructuredSelection;
38import org.eclipse.jface.viewers.ITableLabelProvider;
39import org.eclipse.jface.viewers.LabelProvider;
40import org.eclipse.jface.viewers.Viewer;
41import org.eclipse.jface.viewers.ViewerComparator;
42import org.eclipse.osgi.util.NLS;
43import org.eclipse.swt.SWT;
44import org.eclipse.swt.events.SelectionAdapter;
45import org.eclipse.swt.events.SelectionEvent;
46import org.eclipse.swt.graphics.GC;
47import org.eclipse.swt.graphics.Image;
48import org.eclipse.swt.layout.GridData;
49import org.eclipse.swt.layout.GridLayout;
50import org.eclipse.swt.widgets.Button;
51import org.eclipse.swt.widgets.Composite;
52import org.eclipse.swt.widgets.Control;
53import org.eclipse.swt.widgets.Group;
54import org.eclipse.swt.widgets.Label;
55import org.eclipse.swt.widgets.Table;
56import org.eclipse.swt.widgets.TableColumn;
57import org.eclipse.ui.PlatformUI;
58import org.eclipse.ui.commands.ICommandService;
59import org.eclipse.ui.keys.IBindingService;
60import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
61import org.eclipse.wst.sse.ui.internal.Logger;
62import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
63import org.eclipse.wst.sse.ui.internal.contentassist.CompletionProposalCategory;
64import org.eclipse.wst.sse.ui.internal.contentassist.CompletionProposalComputerRegistry;
65import org.eclipse.wst.sse.ui.internal.util.SWTUtil;
66
67
68/**
69 * <p>A helpful preference configuration block implementation for allowing a user to
70 * set their preferences for which content assist categories to show on the default
71 * content assist page as well as on their own separate page and page ordering for
72 * a specific content type</p>
73 *
74 * @base org.eclipse.jdt.internal.ui.preferences.CodeAssistAdvancedConfigurationBlock
75 */
76public final class CodeAssistCyclingConfigurationBlock {
77
78 /**
79 * <p>Used to compare categories based on their assigned page rank</p>
80 */
81 private final Comparator fCategoryPageComparator = new Comparator() {
82 private int getRank(Object o) {
83 return ((ModelElement) o).getOwnPageRank();
84 }
85
86 public int compare(Object o1, Object o2) {
87 int result = getRank(o1) - getRank(o2);
88 if(result == 0) {
89 result = ((ModelElement) o1).getId().compareTo(((ModelElement) o2).getId());
90 }
91 return result;
92 }
93 };
94
95 /**
96 * <p>Used to compare categories based on their assigned default page rank</p>
97 */
98 private final Comparator fCategoryDefaultPageComparator = new Comparator() {
99 private int getRank(Object o) {
100 return ((ModelElement) o).getDefaultPageRank();
101 }
102
103 public int compare(Object o1, Object o2) {
104 int result = getRank(o1) - getRank(o2);
105 if(result == 0) {
106 result = ((ModelElement) o1).getId().compareTo(((ModelElement) o2).getId());
107 }
108 return result;
109 }
110 };
111
112 /** the preference model for this block */
113 private final PreferenceModel fModel;
114
115 /**
116 * <code>{@link Map}<{@link ImageDescriptor}, {@link Image}></code>
117 */
118 private final Map fImages= new HashMap();
119
120 /** table viewer to configure which categories are displayed on the default page */
121 private CheckboxTableViewer fDefaultPageViewer;
122
123 /**
124 * table viewer to configure which categories are displayed
125 * on their own page, as well as their ordering
126 */
127 private CheckboxTableViewer fOwnPageViewer;
128
129 /** categories pages sort order up button */
130 private Button fPageOrderUpButton;
131
132 /** categories pages sort order down button */
133 private Button fPageOrderDownButton;
134
135 /** categories default page sort order up button */
136 private Button fDefaultPageOrderUpButton;
137
138 /** categories default page sort order down button */
139 private Button fDefaultPageOrderDownButton;
140
141 /** The content type ID this configuration block is for */
142 private String fContentTypeID;
143
144 /** The writable categories configuration */
145 private ICompletionProposalCategoriesConfigurationWriter fConfigurationWriter;
146
147 /**
148 * <p>Creates a new content assist preference block for the given content type
149 * using the given configuration writer</p>
150 *
151 * @param contentTypeID content type this content assist preference block is for
152 * @param configurationWriter {@link ICompletionProposalCategoriesConfigurationWriter} used
153 * to read and write the user preferences
154 */
155 public CodeAssistCyclingConfigurationBlock(String contentTypeID, ICompletionProposalCategoriesConfigurationWriter configurationWriter) {
156 this.fContentTypeID = contentTypeID;
157 this.fConfigurationWriter = configurationWriter;
158
159 List categories = CompletionProposalComputerRegistry.getDefault().getProposalCategories(this.fContentTypeID);
160 this.fModel = new PreferenceModel(categories);
161 }
162
163 /**
164 * <p>Saves the user configuration</p>
165 * @return <code>true</code> if store was successful, <code>false</code> otherwise
166 */
167 public boolean storeValues() {
168 return this.fConfigurationWriter.saveConfiguration();
169 }
170
171 /**
172 * <p>Loads the preference defaults</p>
173 */
174 public void performDefaults() {
175 this.fConfigurationWriter.loadDefaults();
176 this.initializeValues();
177 this.fModel.performDefaults();
178 }
179
180 /**
181 * <p>Disposes of this preference block</p>
182 */
183 public void dispose() {
184 for (Iterator it= fImages.values().iterator(); it.hasNext();) {
185 Image image= (Image) it.next();
186 image.dispose();
187 }
188 }
189
190 /**
191 * <p>Creates the contents of this configuration block using a {@link Group} if
192 * the given <code>groupTitle</code> is not <code>null</code> else creates it
193 * as a composite and in either case adds itself to the given parent</p>
194 *
195 * @param parent {@link Composite} parent to add this configuration block to
196 * @param groupTitle Title to use for the configuration block group, if
197 * <code>null</code> then a {@link Composite} will be used instead of a
198 * {@link Group}
199 *
200 * @return the created configuration block that has already been added to the parent
201 */
202 public Control createContents(Composite parent, String groupTitle) {
203 Composite container;
204 if(groupTitle != null) {
205 container = new Group(parent, SWT.NULL);
206 ((Group)container).setText(groupTitle);
207 } else {
208 container = new Composite(parent, SWT.NULL);
209 }
210 int columns= 2;
211 GridLayout layout= new GridLayout(columns, false);
212 container.setLayout(layout);
213
214 GridData data = new GridData(GridData.FILL);
215 data.horizontalIndent = 0;
216 data.verticalAlignment = GridData.FILL;
217 data.horizontalAlignment = GridData.FILL;
218 data.grabExcessHorizontalSpace = true;
219 container.setLayoutData(data);
220
221 createDefaultPageLabel(container, columns);
222 createDefaultPageSection(container);
223
224 createFiller(container, columns);
225
226 createOwnPageLabel(container, columns);
227 createOwnPageSection(container);
228
229 createFiller(container, columns);
230
231 if (fModel.pageElements.size() > 0) {
232 fDefaultPageViewer.getTable().select(0);
233 fOwnPageViewer.getTable().select(0);
234 handleOwnPageTableSelection();
235 handleDefaultPageTableSelection();
236 }
237
238 return container;
239 }
240
241 /**
242 * <p>Initialize the values of the configuration block</p>
243 */
244 public void initializeValues() {
245 updateCheckedState();
246 fDefaultPageViewer.refresh();
247 fOwnPageViewer.refresh();
248 handleOwnPageTableSelection();
249 handleDefaultPageTableSelection();
250 }
251
252 private void createDefaultPageSection(Composite composite) {
253 createDefaultPageViewer(composite);
254 createDefaultPageButtonList(composite);
255 }
256
257 private void createDefaultPageLabel(Composite composite, int h_span) {
258 final ICommandService commandSvc= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
259 final Command command= commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
260 ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
261 String key= getKeyboardShortcut(pCmd);
262 if (key == null) {
263 key= SSEUIMessages.CodeAssistAdvancedConfigurationBlock_no_shortcut;
264 }
265
266 PixelConverter pixelConverter= new PixelConverter(composite);
267 int width= pixelConverter.convertWidthInCharsToPixels(40);
268
269 Label label= new Label(composite, SWT.NONE | SWT.WRAP);
270 label.setText(NLS.bind(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_page_description, new Object[] { key }));
271 GridData gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
272 gd.widthHint= width;
273 label.setLayoutData(gd);
274
275 createFiller(composite, h_span);
276
277 label= new Label(composite, SWT.NONE | SWT.WRAP);
278 label.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_default_table_description);
279 gd= new GridData(GridData.FILL, GridData.FILL, true, false, h_span, 1);
280 gd.widthHint= width;
281 label.setLayoutData(gd);
282 }
283
284 private void createDefaultPageViewer(Composite composite) {
285 fDefaultPageViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
286 Table table= fDefaultPageViewer.getTable();
287 table.setHeaderVisible(true);
288 table.setLinesVisible(false);
289 table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false, 1, 1));
290
291 TableColumn nameColumn= new TableColumn(table, SWT.NONE);
292 nameColumn.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_default_table_category_column_title);
293 nameColumn.setResizable(false);
294
295 fDefaultPageViewer.addCheckStateListener(new ICheckStateListener() {
296 public void checkStateChanged(CheckStateChangedEvent event) {
297 boolean checked= event.getChecked();
298 ModelElement element= (ModelElement) event.getElement();
299 element.setShouldDisplayOnDefaultPage(checked);
300 }
301 });
302
303 fDefaultPageViewer.setContentProvider(new ArrayContentProvider());
304
305 DefaultPageTableLabelProvider labelProvider= new DefaultPageTableLabelProvider();
306 fDefaultPageViewer.setLabelProvider(labelProvider);
307 fDefaultPageViewer.setInput(fModel.defaultPageElements);
308 fDefaultPageViewer.setComparator(new ModelViewerComparator(fCategoryDefaultPageComparator));
309
310 final int ICON_AND_CHECKBOX_WITH= 50;
311 final int HEADER_MARGIN= 20;
312 int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
313 for (int i= 0; i < fModel.defaultPageElements.size(); i++) {
314 minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.defaultPageElements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
315 }
316
317 nameColumn.setWidth(minNameWidth);
318
319 table.addSelectionListener(new SelectionAdapter() {
320 public void widgetSelected(SelectionEvent e) {
321 handleDefaultPageTableSelection();
322 }
323 });
324 }
325
326 /**
327 * <p>Create the Up and Down buttons for the default page viewer</p>
328 * @param parent {@link Composite} to add the button list to
329 */
330 private void createDefaultPageButtonList(Composite parent) {
331 Composite composite= new Composite(parent, SWT.NONE);
332 composite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
333
334 GridLayout layout= new GridLayout();
335 layout.marginWidth= 0;
336 layout.marginHeight= 0;
337 composite.setLayout(layout);
338
339 fDefaultPageOrderUpButton= new Button(composite, SWT.PUSH | SWT.CENTER);
340 fDefaultPageOrderUpButton.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_Up);
341 fDefaultPageOrderUpButton.addSelectionListener(new SelectionAdapter() {
342 public void widgetSelected(SelectionEvent e) {
343 int index = fDefaultPageViewer.getTable().getSelectionIndex();
344 if (index != -1) {
345 fModel.moveDefaultPageCategoryUp(index);
346 fDefaultPageViewer.refresh();
347 handleDefaultPageTableSelection();
348 }
349 }
350 });
351 fDefaultPageOrderUpButton.setLayoutData(new GridData());
352
353 SWTUtil.setButtonDimensionHint(fDefaultPageOrderUpButton);
354
355 fDefaultPageOrderDownButton= new Button(composite, SWT.PUSH | SWT.CENTER);
356 fDefaultPageOrderDownButton.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_Down);
357 fDefaultPageOrderDownButton.addSelectionListener(new SelectionAdapter() {
358 public void widgetSelected(SelectionEvent e) {
359 int index= fDefaultPageViewer.getTable().getSelectionIndex();
360 if (index != -1) {
361 fModel.moveDefaultPageCategoryDown(index);
362 fDefaultPageViewer.refresh();
363 handleDefaultPageTableSelection();
364 }
365 }
366 });
367 fDefaultPageOrderDownButton.setLayoutData(new GridData());
368 SWTUtil.setButtonDimensionHint(fDefaultPageOrderDownButton);
369 }
370
371 private void createFiller(Composite composite, int h_span) {
372 Label filler= new Label(composite, SWT.NONE);
373 filler.setVisible(false);
374 filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, h_span, 1));
375 }
376
377 private void createOwnPageLabel(Composite composite, int h_span) {
378 PixelConverter pixelConverter= new PixelConverter(composite);
379 int width= pixelConverter.convertWidthInCharsToPixels(40);
380
381 Label label= new Label(composite, SWT.NONE | SWT.WRAP);
382 label.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_separate_table_description);
383 GridData gd= new GridData(GridData.FILL, GridData.FILL, false, false, h_span, 1);
384 gd.widthHint= width;
385 label.setLayoutData(gd);
386 }
387
388 private void createOwnPageSection(Composite composite) {
389 createOwnPageViewer(composite);
390 createOwnPageButtonList(composite);
391 }
392
393 private void createOwnPageViewer(Composite composite) {
394 fOwnPageViewer= CheckboxTableViewer.newCheckList(composite, SWT.SINGLE | SWT.BORDER);
395 Table table= fOwnPageViewer.getTable();
396 table.setHeaderVisible(true);
397 table.setLinesVisible(false);
398 table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, 1, 1));
399
400 TableColumn nameColumn= new TableColumn(table, SWT.NONE);
401 nameColumn.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_separate_table_category_column_title);
402 nameColumn.setResizable(false);
403
404 fOwnPageViewer.setContentProvider(new ArrayContentProvider());
405
406 ITableLabelProvider labelProvider= new OwnPageTableLabelProvider();
407 fOwnPageViewer.setLabelProvider(labelProvider);
408 fOwnPageViewer.setInput(fModel.pageElements);
409 fOwnPageViewer.setComparator(new ModelViewerComparator(fCategoryPageComparator));
410
411 final int ICON_AND_CHECKBOX_WITH= 50;
412 final int HEADER_MARGIN= 20;
413 int minNameWidth= computeWidth(table, nameColumn.getText()) + HEADER_MARGIN;
414 for (int i= 0; i < fModel.pageElements.size(); i++) {
415 minNameWidth= Math.max(minNameWidth, computeWidth(table, labelProvider.getColumnText(fModel.pageElements.get(i), 0)) + ICON_AND_CHECKBOX_WITH);
416 }
417
418 nameColumn.setWidth(minNameWidth);
419
420 fOwnPageViewer.addCheckStateListener(new ICheckStateListener() {
421 public void checkStateChanged(CheckStateChangedEvent event) {
422 boolean checked= event.getChecked();
423 ModelElement element= (ModelElement) event.getElement();
424 element.setShouldDisplayOnOwnPage(checked);
425 }
426 });
427
428 table.addSelectionListener(new SelectionAdapter() {
429 public void widgetSelected(SelectionEvent e) {
430 handleOwnPageTableSelection();
431 }
432 });
433
434 }
435
436 /**
437 * <p>Create the Up and Down buttons for the own page viewer</p>
438 * @param parent {@link Composite} to add the button list to
439 */
440 private void createOwnPageButtonList(Composite parent) {
441 Composite composite= new Composite(parent, SWT.NONE);
442 composite.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
443
444 GridLayout layout= new GridLayout();
445 layout.marginWidth= 0;
446 layout.marginHeight= 0;
447 composite.setLayout(layout);
448
449 fPageOrderUpButton= new Button(composite, SWT.PUSH | SWT.CENTER);
nsandonato74504672010-04-19 17:17:04 +0000450 fPageOrderUpButton.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_PagesUp);
nsandonato3b334302010-02-26 20:59:38 +0000451 fPageOrderUpButton.addSelectionListener(new SelectionAdapter() {
452 public void widgetSelected(SelectionEvent e) {
453 int index = fOwnPageViewer.getTable().getSelectionIndex();
454 if (index != -1) {
455 fModel.movePageUp(index);
456 fOwnPageViewer.refresh();
457 handleOwnPageTableSelection();
458 }
459 }
460 });
461 fPageOrderUpButton.setLayoutData(new GridData());
462
463 SWTUtil.setButtonDimensionHint(fPageOrderUpButton);
464
465 fPageOrderDownButton= new Button(composite, SWT.PUSH | SWT.CENTER);
nsandonato74504672010-04-19 17:17:04 +0000466 fPageOrderDownButton.setText(SSEUIMessages.CodeAssistAdvancedConfigurationBlock_PagesDown);
nsandonato3b334302010-02-26 20:59:38 +0000467 fPageOrderDownButton.addSelectionListener(new SelectionAdapter() {
468 public void widgetSelected(SelectionEvent e) {
469 int index= fOwnPageViewer.getTable().getSelectionIndex();
470 if (index != -1) {
471 fModel.movePageDown(index);
472 fOwnPageViewer.refresh();
473 handleOwnPageTableSelection();
474 }
475 }
476 });
477 fPageOrderDownButton.setLayoutData(new GridData());
478 SWTUtil.setButtonDimensionHint(fPageOrderDownButton);
479 }
480
481 /**
482 * <p>Update the enablement of the Up and Down buttons for the own page table viewer</p>
483 */
484 private void handleOwnPageTableSelection() {
485 ModelElement item= (ModelElement) ((IStructuredSelection) fOwnPageViewer.getSelection()).getFirstElement();
486 if (item != null) {
487 int index= fOwnPageViewer.getTable().getSelectionIndex();
488 fPageOrderUpButton.setEnabled(index > 0);
489 fPageOrderDownButton.setEnabled(index < fModel.pageElements.size() - 1);
490 } else {
491 fPageOrderUpButton.setEnabled(false);
492 fPageOrderDownButton.setEnabled(false);
493 }
494 }
495
496 /**
497 * <p>Update the enablement of the Up and Down buttons for the default page table viewer</p>
498 */
499 private void handleDefaultPageTableSelection() {
500 ModelElement item= (ModelElement) ((IStructuredSelection) fDefaultPageViewer.getSelection()).getFirstElement();
501 if (item != null) {
502 int index = fDefaultPageViewer.getTable().getSelectionIndex();
503 fDefaultPageOrderUpButton.setEnabled(index > 0);
504 fDefaultPageOrderDownButton.setEnabled(index < fModel.defaultPageElements.size() - 1);
505 } else {
506 fDefaultPageOrderUpButton.setEnabled(false);
507 fDefaultPageOrderDownButton.setEnabled(false);
508 }
509 }
510
511 private void updateCheckedState() {
512 /* does not matter which set of elements we use here
513 * because order does not matter in this case
514 */
515 final int size= fModel.pageElements.size();
516 List defaultChecked= new ArrayList(size);
517 List separateChecked= new ArrayList(size);
518
519 for (Iterator it= fModel.pageElements.iterator(); it.hasNext();) {
520 ModelElement element= (ModelElement) it.next();
521 if (element.shouldDisplayOnDefaultPage())
522 defaultChecked.add(element);
523 if (element.shouldDisplayOnOwnPage())
524 separateChecked.add(element);
525 }
526
527 fDefaultPageViewer.setCheckedElements(defaultChecked.toArray(new Object[defaultChecked.size()]));
528 fOwnPageViewer.setCheckedElements(separateChecked.toArray(new Object[separateChecked.size()]));
529 }
530
531 private int computeWidth(Control control, String name) {
532 if (name == null)
533 return 0;
534 GC gc= new GC(control);
535 try {
536 gc.setFont(JFaceResources.getDialogFont());
537 return gc.stringExtent(name).x + 10;
538 } finally {
539 gc.dispose();
540 }
541 }
542
543 private static BindingManager fgLocalBindingManager;
544 static {
545 fgLocalBindingManager= new BindingManager(new ContextManager(), new CommandManager());
546 final IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getService(IBindingService.class);
547 final Scheme[] definedSchemes= bindingService.getDefinedSchemes();
548 if (definedSchemes != null) {
549 try {
550 for (int i = 0; i < definedSchemes.length; i++) {
551 final Scheme scheme= definedSchemes[i];
552 final Scheme copy= fgLocalBindingManager.getScheme(scheme.getId());
553 copy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId());
554 }
555 } catch (final NotDefinedException e) {
556 Logger.logException(e);
557 }
558 }
559 fgLocalBindingManager.setLocale(bindingService.getLocale());
560 fgLocalBindingManager.setPlatform(bindingService.getPlatform());
561 }
562
563 private static String getKeyboardShortcut(ParameterizedCommand command) {
564 IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
565 fgLocalBindingManager.setBindings(bindingService.getBindings());
566 try {
567 Scheme activeScheme= bindingService.getActiveScheme();
568 if (activeScheme != null)
569 fgLocalBindingManager.setActiveScheme(activeScheme);
570 } catch (NotDefinedException e) {
571 Logger.logException(e);
572 }
573
574 TriggerSequence[] bindings= fgLocalBindingManager.getActiveBindingsDisregardingContextFor(command);
575 if (bindings.length > 0)
576 return bindings[0].format();
577 return null;
578 }
579
580 /**
581 * <p>Gets and image based on an image descriptor, and stores the image so it
582 * does not have to be created more then once</p>
583 *
584 * @param imgDesc {@link ImageDescriptor} to get the {@link Image} for
585 * @return {@link Image} created from the {@link ImageDescriptor}, or stored
586 * {@link Image} associated with the given {@link ImageDescriptor} if an
587 * {@link Image} had already been created for the given {@link ImageDescriptor}
588 */
589 private Image getImage(ImageDescriptor imgDesc) {
590 if (imgDesc == null)
591 return null;
592
593 Image img= (Image) fImages.get(imgDesc);
594 if (img == null) {
595 img= imgDesc.createImage(false);
596 fImages.put(imgDesc, img);
597 }
598 return img;
599 }
600
601 /**
602 * <p>Label provider for the table for configuring which categories should be displayed on the
603 * default assist page</p>
604 */
605 private final class DefaultPageTableLabelProvider extends LabelProvider implements ITableLabelProvider {
606 /**
607 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
608 */
609 public Image getColumnImage(Object element, int columnIndex) {
610 if (columnIndex == 0)
611 return ((ModelElement) element).getImage();
612 return null;
613 }
614
615 /**
616 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
617 */
618 public String getColumnText(Object element, int columnIndex) {
619 switch (columnIndex) {
620 case 0:
621 return ((ModelElement) element).getName();
622 default:
623 Assert.isTrue(false);
624 return null;
625 }
626 }
627
628 /**
629 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
630 */
631 public String getText(Object element) {
632 return getColumnText(element, 0); // needed to make the sorter work
633 }
634 }
635
636 /**
637 * <p>Label provider for the table for configuring which categories should be displayed on their
638 * own content assist page</p>
639 */
640 private final class OwnPageTableLabelProvider extends LabelProvider implements ITableLabelProvider {
641 /**
642 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
643 */
644 public Image getColumnImage(Object element, int columnIndex) {
645 if (columnIndex == 0)
646 return ((ModelElement) element).getImage();
647 return null;
648 }
649
650 /**
651 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
652 */
653 public String getColumnText(Object element, int columnIndex) {
654 switch (columnIndex) {
655 case 0:
656 return ((ModelElement) element).getName();
657 default:
658 Assert.isTrue(false);
659 return null;
660 }
661 }
662 }
663
664 /**
665 * <p>PreferenceModel used to read and write the user preferences
666 * using the {@link ICompletionProposalCategoriesConfigurationWriter}</p>
667 */
668 private final class PreferenceModel {
669 /** private modifiable page element list */
670 private final List fPageElements;
671
672 /** public unmodifiable page element list */
673 final List pageElements;
674
675 /** private modifiable default page element list */
676 private final List fDefaultPageElements;
677
678 /** public unmodifiable default page element list */
679 final List defaultPageElements;
680
681 /**
682 * <p>Create the preference model for the given categories</p>
683 *
684 * @param categories <code>{@link List}<{@link CompletionProposalCategory}></code>
685 */
686 public PreferenceModel(List categories) {
687 //need separate lists because they will be ordered differently
688 this.fPageElements = new ArrayList();
689 this.fDefaultPageElements = new ArrayList();
690 for (Iterator it= categories.iterator(); it.hasNext();) {
691 CompletionProposalCategory category= (CompletionProposalCategory) it.next();
692 if (category.hasComputers()) {
693 ModelElement elem = new ModelElement(category);
694 fPageElements.add(elem);
695 fDefaultPageElements.add(elem);
696 }
697 }
698 //sort the lists
699 this.performDefaults();
700
701 pageElements = Collections.unmodifiableList(fPageElements);
702 defaultPageElements = Collections.unmodifiableList(fDefaultPageElements);
703 }
704
705 /**
706 * <p>Move the model element specified by the given index
707 * up in the content assist page order</p>
708 *
709 * @param elementIndex the index of the model element to move up
710 */
711 public void movePageUp(int elementIndex) {
712 Object removed = fPageElements.remove(elementIndex);
713 fPageElements.add(elementIndex-1, removed);
714
715 fConfigurationWriter.setPageOrder(getPageOrderedCategoryIDs());
716 }
717
718 /**
719 * <p>Move the model element specified by the given index
720 * down in the content assist page order</p>
721 *
722 * @param elementIndex the index of the model element to move up
723 */
724 public void movePageDown(int elementIndex) {
725 Object removed = fPageElements.remove(elementIndex);
726 fPageElements.add(elementIndex+1, removed);
727
728 fConfigurationWriter.setPageOrder(getPageOrderedCategoryIDs());
729 }
730
731 /**
732 * <p>Move the model element specified by the given index
733 * up in the content assist page order</p>
734 *
735 * @param elementIndex the index of the model element to move up
736 */
737 public void moveDefaultPageCategoryUp(int elementIndex) {
738 Object removed = fDefaultPageElements.remove(elementIndex);
739 fDefaultPageElements.add(elementIndex-1, removed);
740
741 fConfigurationWriter.setDefaultPageOrder(getDefaultPageOrderedCategoryIDs());
742 }
743
744 /**
745 * <p>Move the model element specified by the given index
746 * down in the content assist page order</p>
747 *
748 * @param elementIndex the index of the model element to move up
749 */
750 public void moveDefaultPageCategoryDown(int elementIndex) {
751 Object removed = fDefaultPageElements.remove(elementIndex);
752 fDefaultPageElements.add(elementIndex+1, removed);
753
754 fConfigurationWriter.setDefaultPageOrder(getDefaultPageOrderedCategoryIDs());
755 }
756
757 /**
758 * @return <code>{@link List}<{@link String}></code> -
759 * List of category IDs by page order
760 */
761 private List getPageOrderedCategoryIDs() {
762 List ordered = new ArrayList(pageElements.size());
763 for(int i = 0; i < pageElements.size(); ++i) {
764 ordered.add(((ModelElement)pageElements.get(i)).getId());
765 }
766
767 return ordered;
768 }
769
770 /**
771 * @return <code>{@link List}<{@link String}></code> -
772 * List of category IDs by default page order
773 */
774 private List getDefaultPageOrderedCategoryIDs() {
775 List ordered = new ArrayList(defaultPageElements.size());
776 for(int i = 0; i < defaultPageElements.size(); ++i) {
777 ordered.add(((ModelElement)defaultPageElements.get(i)).getId());
778 }
779
780 return ordered;
781 }
782
783 /**
784 * <p>need to re-sort the lists after performing defaults</p>
785 */
786 public void performDefaults() {
787 Collections.sort(fPageElements, fCategoryPageComparator);
788 Collections.sort(fDefaultPageElements, fCategoryDefaultPageComparator);
789 }
790 }
791
792 /**
793 * <p>Wraps a {@link CompletionProposalCategory} for use in the {@link PreferenceModel}</p>
794 */
795 private final class ModelElement {
796 /** The wrapped category */
797 private final CompletionProposalCategory fCategory;
798
799 /**
800 * <p>Create a new model element wrapping the given category</p>
801 *
802 * @param category {@link CompletionProposalCategory} to be wrapped by this model element
803 * for use in the {@link PreferenceModel}
804 */
805 ModelElement(CompletionProposalCategory category) {
806 fCategory= category;
807 }
808
809 /**
810 * @return {@link Image} associated with the wrapped category
811 */
812 Image getImage() {
813 return CodeAssistCyclingConfigurationBlock.this.getImage(fCategory.getImageDescriptor());
814 }
815
816 /**
817 * @return name of the wrapped category
818 */
819 String getName() {
820 return fCategory.getDisplayName();
821 }
822
823 String getId() {
824 return fCategory.getId();
825 }
826
827 /**
828 * @return <code>true</code> if the wrapped category should be displayed on the
829 * default content assist page, <code>false</code> otherwise
830 */
831 boolean shouldDisplayOnDefaultPage() {
832 return fConfigurationWriter.shouldDisplayOnDefaultPage(this.getId());
833 }
834
835 /**
836 * @param included <code>true</code> if the wrapped category should be displayed on the
837 * default content assist page, <code>false</code> otherwise
838 */
839 void setShouldDisplayOnDefaultPage(boolean included) {
840 fConfigurationWriter.setShouldDisplayOnDefaultPage(this.getId(), included);
841 }
842
843 /**
844 * @return <code>true</code> if the wrapped category should be displayed on the
845 * its own content assist page, <code>false</code> otherwise
846 */
847 boolean shouldDisplayOnOwnPage() {
848 return fConfigurationWriter.shouldDisplayOnOwnPage(this.getId());
849 }
850
851 /**
852 * @param shouldDisplay <code>true</code> if the wrapped category should be displayed on the
853 * its own content assist page, <code>false</code> otherwise
854 */
855 void setShouldDisplayOnOwnPage(boolean shouldDisplay) {
856 fConfigurationWriter.setShouldDisplayOnOwnPage(this.getId(), shouldDisplay);
857 }
858
859 /**
860 * @return the wrapped categories content assist page sort rank compared to the
861 * other categories
862 */
863 int getOwnPageRank() {
864 return fConfigurationWriter.getPageSortOrder(this.getId());
865 }
866
867 /**
868 * @return the wrapped categories content assist page sort rank compared to the
869 * other categories
870 */
871 int getDefaultPageRank() {
872 return fConfigurationWriter.getDefaultPageSortOrder(this.getId());
873 }
874 }
875
876 private class ModelViewerComparator extends ViewerComparator {
877 /**
878 *
879 */
880 public ModelViewerComparator(Comparator comparator) {
881 super(comparator);
882 }
883
884 /**
885 * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
886 */
887 public int compare(Viewer viewer, Object e1, Object e2) {
888 return this.getComparator().compare(e1, e2);
889 }
890 }
891}