1 /******************************************************************************* 2 * Copyright (c) 2005, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Remy Chi Jian Suen <remy.suen@gmail.com> - 14 * Bug 186522 - [KeyBindings] New Keys preference page does not resort by binding with conflicts 15 * Bug 226342 - [KeyBindings] Keys preference page conflict table is hard to read 16 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 440810, 491393 17 * Cornel Izbasa <cizbasa@info.uvt.ro> - Bug 442215 18 * Christian Georgi (SAP SE) - Bug 540440 19 *******************************************************************************/ 20 21 package org.eclipse.ui.internal.keys; 22 23 import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; 24 25 import java.util.ArrayList; 26 import java.util.Collection; 27 import java.util.Iterator; 28 import java.util.LinkedList; 29 import java.util.Map; 30 import org.eclipse.core.commands.Category; 31 import org.eclipse.core.commands.ParameterizedCommand; 32 import org.eclipse.core.commands.util.Tracing; 33 import org.eclipse.core.runtime.IStatus; 34 import org.eclipse.core.runtime.Status; 35 import org.eclipse.jface.action.LegacyActionTools; 36 import org.eclipse.jface.bindings.Binding; 37 import org.eclipse.jface.bindings.TriggerSequence; 38 import org.eclipse.jface.bindings.keys.KeySequence; 39 import org.eclipse.jface.bindings.keys.KeySequenceText; 40 import org.eclipse.jface.bindings.keys.KeyStroke; 41 import org.eclipse.jface.dialogs.IDialogConstants; 42 import org.eclipse.jface.dialogs.IDialogSettings; 43 import org.eclipse.jface.dialogs.MessageDialog; 44 import org.eclipse.jface.preference.IPreferenceStore; 45 import org.eclipse.jface.preference.PreferencePage; 46 import org.eclipse.jface.resource.DeviceResourceException; 47 import org.eclipse.jface.resource.ImageDescriptor; 48 import org.eclipse.jface.resource.JFaceResources; 49 import org.eclipse.jface.resource.LocalResourceManager; 50 import org.eclipse.jface.util.IPropertyChangeListener; 51 import org.eclipse.jface.viewers.ColumnWeightData; 52 import org.eclipse.jface.viewers.ComboViewer; 53 import org.eclipse.jface.viewers.IBaseLabelProvider; 54 import org.eclipse.jface.viewers.ISelection; 55 import org.eclipse.jface.viewers.IStructuredContentProvider; 56 import org.eclipse.jface.viewers.ITableLabelProvider; 57 import org.eclipse.jface.viewers.ITreeContentProvider; 58 import org.eclipse.jface.viewers.LabelProvider; 59 import org.eclipse.jface.viewers.StructuredSelection; 60 import org.eclipse.jface.viewers.TableLayout; 61 import org.eclipse.jface.viewers.TableViewer; 62 import org.eclipse.jface.viewers.TreeViewer; 63 import org.eclipse.jface.viewers.Viewer; 64 import org.eclipse.jface.viewers.ViewerComparator; 65 import org.eclipse.jface.window.Window; 66 import org.eclipse.swt.SWT; 67 import org.eclipse.swt.custom.BusyIndicator; 68 import org.eclipse.swt.events.FocusEvent; 69 import org.eclipse.swt.events.FocusListener; 70 import org.eclipse.swt.events.SelectionAdapter; 71 import org.eclipse.swt.events.SelectionEvent; 72 import org.eclipse.swt.events.SelectionListener; 73 import org.eclipse.swt.graphics.FontMetrics; 74 import org.eclipse.swt.graphics.GC; 75 import org.eclipse.swt.graphics.Image; 76 import org.eclipse.swt.graphics.Point; 77 import org.eclipse.swt.layout.GridData; 78 import org.eclipse.swt.layout.GridLayout; 79 import org.eclipse.swt.widgets.Button; 80 import org.eclipse.swt.widgets.Composite; 81 import org.eclipse.swt.widgets.Control; 82 import org.eclipse.swt.widgets.Group; 83 import org.eclipse.swt.widgets.Label; 84 import org.eclipse.swt.widgets.Menu; 85 import org.eclipse.swt.widgets.MenuItem; 86 import org.eclipse.swt.widgets.Table; 87 import org.eclipse.swt.widgets.TableColumn; 88 import org.eclipse.swt.widgets.Text; 89 import org.eclipse.swt.widgets.Tree; 90 import org.eclipse.swt.widgets.TreeColumn; 91 import org.eclipse.swt.widgets.TreeItem; 92 import org.eclipse.ui.IWorkbench; 93 import org.eclipse.ui.IWorkbenchPreferencePage; 94 import org.eclipse.ui.PlatformUI; 95 import org.eclipse.ui.commands.ICommandImageService; 96 import org.eclipse.ui.commands.ICommandService; 97 import org.eclipse.ui.dialogs.FilteredTree; 98 import org.eclipse.ui.internal.IPreferenceConstants; 99 import org.eclipse.ui.internal.IWorkbenchHelpContextIds; 100 import org.eclipse.ui.internal.WorkbenchPlugin; 101 import org.eclipse.ui.internal.keys.model.BindingElement; 102 import org.eclipse.ui.internal.keys.model.BindingModel; 103 import org.eclipse.ui.internal.keys.model.CommonModel; 104 import org.eclipse.ui.internal.keys.model.ConflictModel; 105 import org.eclipse.ui.internal.keys.model.ContextElement; 106 import org.eclipse.ui.internal.keys.model.ContextModel; 107 import org.eclipse.ui.internal.keys.model.KeyController; 108 import org.eclipse.ui.internal.keys.model.ModelElement; 109 import org.eclipse.ui.internal.keys.model.SchemeElement; 110 import org.eclipse.ui.internal.keys.model.SchemeModel; 111 import org.eclipse.ui.internal.keys.show.ShowKeysToggleHandler; 112 import org.eclipse.ui.internal.keys.show.ShowKeysUI; 113 import org.eclipse.ui.internal.misc.Policy; 114 import org.eclipse.ui.internal.util.Util; 115 import org.eclipse.ui.keys.IBindingService; 116 117 /** 118 * <p> 119 * A preference page that is capable of displaying and editing the bindings 120 * between commands and user input events. These are typically things like 121 * keyboard shortcuts. 122 * </p> 123 * <p> 124 * This preference page has four general types of methods. Create methods are 125 * called when the page is first made visible. They are responsible for creating 126 * all of the widgets, and laying them out within the preference page. Fill 127 * methods populate the contents of the widgets that contain collections of data 128 * from which items can be selected. The select methods respond to selection 129 * events from the user, such as a button press or a table selection. The update 130 * methods update the contents of various widgets based on the current state of 131 * the user interface. For example, the command name label will always try to 132 * match the current select in the binding table. 133 * </p> 134 * <p> 135 * Updated in 3.4 to work with a model backed by the real KeyBinding and 136 * ParameterizedCommand objects. 137 * </p> 138 * 139 * @since 3.2 140 */ 141 public class NewKeysPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { 142 143 private static boolean DEBUG = Policy.DEBUG_KEY_BINDINGS; 144 145 private static final String TRACING_COMPONENT = "NewKeysPref"; //$NON-NLS-1$ 146 147 public static final String TAG_DIALOG_SECTION = "org.eclipse.ui.preferences.keysPreferencePage"; //$NON-NLS-1$ 148 149 private static final String TAG_FILTER_ACTION_SETS = "actionSetFilter"; //$NON-NLS-1$ 150 151 private static final String TAG_FILTER_INTERNAL = "internalFilter"; //$NON-NLS-1$ 152 153 private static final String TAG_FILTER_UNCAT = "uncategorizedFilter"; //$NON-NLS-1$ 154 155 /** 156 * The number of items to show in the bindings table tree. 157 */ 158 private static final int ITEMS_TO_SHOW = 12; 159 160 private static final int COMMAND_NAME_COLUMN = 0; 161 private static final int KEY_SEQUENCE_COLUMN = 1; 162 private static final int CONTEXT_COLUMN = 2; 163 private static final int CATEGORY_COLUMN = 3; 164 private static final int USER_DELTA_COLUMN = 4; 165 private static int NUM_OF_COLUMNS = USER_DELTA_COLUMN + 1; 166 167 private ComboViewer fSchemeCombo; 168 169 private CategoryPatternFilter fPatternFilter; 170 171 private CategoryFilterTree fFilteredTree; 172 173 private boolean fFilterActionSetContexts = true; 174 175 private boolean fFilterInternalContexts = true; 176 177 private KeyController keyController; 178 179 private Category fDefaultCategory; 180 181 private Label commandNameValueLabel; 182 183 private Text fBindingText; 184 185 private Text fDescriptionText; 186 187 private ComboViewer fWhenCombo; 188 189 private IBindingService fBindingService; 190 191 private KeySequenceText fKeySequenceText; 192 193 private TableViewer conflictViewer; 194 195 private Button fShowCommandKey; 196 private Button fShowCommandKeyForMouseEvents; 197 198 private ICommandImageService commandImageService; 199 200 private ICommandService commandService; 201 202 private IWorkbench fWorkbench; 203 204 /** 205 * A FilteredTree that provides a combo which is used to organize and display 206 * elements in the tree according to the selected criteria. 207 * 208 */ 209 protected static class CategoryFilterTree extends FilteredTree { 210 211 private CategoryPatternFilter filter; 212 213 /** 214 * Constructor for PatternFilteredTree. 215 * 216 * @param parent 217 * @param treeStyle 218 * @param filter 219 */ CategoryFilterTree(Composite parent, int treeStyle, CategoryPatternFilter filter)220 protected CategoryFilterTree(Composite parent, int treeStyle, CategoryPatternFilter filter) { 221 super(parent, treeStyle, filter, true); 222 this.filter = filter; 223 setQuickSelectionMode(true); 224 } 225 filterCategories(boolean b)226 public void filterCategories(boolean b) { 227 filter.filterCategories(b); 228 textChanged(); 229 } 230 isFilteringCategories()231 public boolean isFilteringCategories() { 232 return filter.isFilteringCategories(); 233 } 234 } 235 236 private final class BindingModelComparator extends ViewerComparator { 237 private LinkedList<Integer> sortColumns = new LinkedList<>(); 238 private boolean ascending = true; 239 BindingModelComparator()240 public BindingModelComparator() { 241 for (int i = 0; i < NUM_OF_COLUMNS; i++) { 242 sortColumns.add(Integer.valueOf(i)); 243 } 244 } 245 getSortColumn()246 public int getSortColumn() { 247 return sortColumns.getFirst().intValue(); 248 } 249 setSortColumn(int column)250 public void setSortColumn(int column) { 251 if (column == getSortColumn()) { 252 return; 253 } 254 Integer sortColumn = Integer.valueOf(column); 255 sortColumns.remove(sortColumn); 256 sortColumns.addFirst(sortColumn); 257 } 258 259 /** 260 * @return Returns the ascending. 261 */ isAscending()262 public boolean isAscending() { 263 return ascending; 264 } 265 266 /** 267 * @param ascending The ascending to set. 268 */ setAscending(boolean ascending)269 public void setAscending(boolean ascending) { 270 this.ascending = ascending; 271 } 272 273 @Override compare(final Viewer viewer, final Object a, final Object b)274 public int compare(final Viewer viewer, final Object a, final Object b) { 275 int result = 0; 276 Iterator<Integer> i = sortColumns.iterator(); 277 while (i.hasNext() && result == 0) { 278 int column = i.next().intValue(); 279 result = compareColumn(viewer, a, b, column); 280 } 281 return ascending ? result : (-1) * result; 282 } 283 compareColumn(final Viewer viewer, final Object a, final Object b, final int columnNumber)284 private int compareColumn(final Viewer viewer, final Object a, final Object b, final int columnNumber) { 285 if (columnNumber == USER_DELTA_COLUMN) { 286 return sortUser(a, b); 287 } 288 IBaseLabelProvider baseLabel = ((TreeViewer) viewer).getLabelProvider(); 289 if (baseLabel instanceof ITableLabelProvider) { 290 ITableLabelProvider tableProvider = (ITableLabelProvider) baseLabel; 291 String e1p = tableProvider.getColumnText(a, columnNumber); 292 String e2p = tableProvider.getColumnText(b, columnNumber); 293 if (e1p != null && e2p != null) { 294 return getComparator().compare(e1p, e2p); 295 } 296 } 297 return 0; 298 } 299 sortUser(final Object a, final Object b)300 private int sortUser(final Object a, final Object b) { 301 int typeA = ((BindingElement) a).getUserDelta().intValue(); 302 int typeB = ((BindingElement) b).getUserDelta().intValue(); 303 return typeA - typeB; 304 } 305 306 } 307 308 private final class ResortColumn extends SelectionAdapter { 309 private final BindingModelComparator comparator; 310 private final TreeColumn treeColumn; 311 private final TreeViewer viewer; 312 private final int column; 313 ResortColumn(BindingModelComparator comparator, TreeColumn treeColumn, TreeViewer viewer, int column)314 private ResortColumn(BindingModelComparator comparator, TreeColumn treeColumn, TreeViewer viewer, int column) { 315 this.comparator = comparator; 316 this.treeColumn = treeColumn; 317 this.viewer = viewer; 318 this.column = column; 319 } 320 321 @Override widgetSelected(SelectionEvent e)322 public void widgetSelected(SelectionEvent e) { 323 if (comparator.getSortColumn() == column) { 324 comparator.setAscending(!comparator.isAscending()); 325 viewer.getTree().setSortDirection(comparator.isAscending() ? SWT.UP : SWT.DOWN); 326 } else { 327 viewer.getTree().setSortColumn(treeColumn); 328 comparator.setSortColumn(column); 329 } 330 try { 331 viewer.getTree().setRedraw(false); 332 viewer.refresh(); 333 } finally { 334 viewer.getTree().setRedraw(true); 335 } 336 } 337 } 338 339 private static class ListLabelProvider extends LabelProvider { 340 @Override getText(Object element)341 public String getText(Object element) { 342 return ((ModelElement) element).getName(); 343 } 344 } 345 346 private class BindingElementLabelProvider extends LabelProvider implements ITableLabelProvider { 347 /** 348 * A resource manager for this preference page. 349 */ 350 private final LocalResourceManager localResourceManager = new LocalResourceManager( 351 JFaceResources.getResources()); 352 353 @Override dispose()354 public final void dispose() { 355 super.dispose(); 356 localResourceManager.dispose(); 357 } 358 359 @Override getText(Object element)360 public String getText(Object element) { 361 String rc = getColumnText(element, 0); 362 if (rc == null) { 363 rc = super.getText(element); 364 } 365 StringBuilder buf = new StringBuilder(rc); 366 for (int i = 1; i < USER_DELTA_COLUMN; i++) { 367 String text = getColumnText(element, i); 368 if (text != null) { 369 buf.append(' '); 370 buf.append(text); 371 } 372 } 373 return buf.toString(); 374 } 375 376 @Override getColumnText(Object element, int index)377 public String getColumnText(Object element, int index) { 378 BindingElement bindingElement = ((BindingElement) element); 379 switch (index) { 380 case COMMAND_NAME_COLUMN: // name 381 return LegacyActionTools.removeMnemonics(bindingElement.getName()); 382 case KEY_SEQUENCE_COLUMN: // keys 383 TriggerSequence seq = bindingElement.getTrigger(); 384 return seq == null ? Util.ZERO_LENGTH_STRING : seq.format(); 385 case CONTEXT_COLUMN: // when 386 ModelElement context = bindingElement.getContext(); 387 return context == null ? Util.ZERO_LENGTH_STRING : context.getName(); 388 case CATEGORY_COLUMN: // category 389 return bindingElement.getCategory(); 390 case USER_DELTA_COLUMN: // user 391 if (bindingElement.getUserDelta().intValue() == Binding.USER) { 392 if (bindingElement.getConflict().equals(Boolean.TRUE)) { 393 return "CU"; //$NON-NLS-1$ 394 } 395 return " U"; //$NON-NLS-1$ 396 } 397 if (bindingElement.getConflict().equals(Boolean.TRUE)) { 398 return "C "; //$NON-NLS-1$ 399 } 400 return " "; //$NON-NLS-1$ 401 } 402 return null; 403 } 404 405 @Override getColumnImage(Object element, int index)406 public Image getColumnImage(Object element, int index) { 407 BindingElement be = (BindingElement) element; 408 switch (index) { 409 case COMMAND_NAME_COLUMN: 410 final String commandId = be.getId(); 411 final ImageDescriptor imageDescriptor = commandImageService.getImageDescriptor(commandId); 412 if (imageDescriptor == null) { 413 return null; 414 } 415 try { 416 return localResourceManager.createImage(imageDescriptor); 417 } catch (final DeviceResourceException e) { 418 final String message = "Problem retrieving image for a command '" //$NON-NLS-1$ 419 + commandId + '\''; 420 final IStatus status = new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, 0, message, e); 421 WorkbenchPlugin.log(message, status); 422 } 423 return null; 424 425 } 426 427 return null; 428 } 429 } 430 431 class ModelContentProvider implements ITreeContentProvider { 432 @Override getChildren(Object parentElement)433 public Object[] getChildren(Object parentElement) { 434 if (parentElement instanceof BindingModel) { 435 return ((BindingModel) parentElement).getBindings().toArray(); 436 } 437 if (parentElement instanceof ContextModel) { 438 return ((ContextModel) parentElement).getContexts().toArray(); 439 } 440 if (parentElement instanceof SchemeModel) { 441 return ((SchemeModel) parentElement).getSchemes().toArray(); 442 } 443 return new Object[0]; 444 } 445 446 @Override getParent(Object element)447 public Object getParent(Object element) { 448 return ((ModelElement) element).getParent(); 449 } 450 451 @Override hasChildren(Object element)452 public boolean hasChildren(Object element) { 453 return (element instanceof BindingModel) || (element instanceof ContextModel) 454 || (element instanceof SchemeModel); 455 } 456 457 @Override getElements(Object inputElement)458 public Object[] getElements(Object inputElement) { 459 return getChildren(inputElement); 460 } 461 462 } 463 464 @Override createContents(Composite parent)465 protected Control createContents(Composite parent) { 466 PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IWorkbenchHelpContextIds.KEYS_PREFERENCE_PAGE); 467 final Composite page = new Composite(parent, SWT.NONE); 468 GridLayout layout = new GridLayout(1, false); 469 layout.marginWidth = 0; 470 page.setLayout(layout); 471 472 IDialogSettings settings = getDialogSettings(); 473 474 fPatternFilter = new CategoryPatternFilter(true, commandService.getCategory(null)); 475 if (settings.get(TAG_FILTER_UNCAT) != null) { 476 fPatternFilter.filterCategories(settings.getBoolean(TAG_FILTER_UNCAT)); 477 } 478 479 createSchemeControls(page); 480 createTree(page); 481 createTreeControls(page); 482 createDataControls(page); 483 createShowKeysControls(page); 484 485 fill(); 486 487 applyDialogFont(page); 488 489 // we want the description text control to span four lines, but because 490 // we need the dialog's font for this information, we have to set it here 491 // after the dialog font has been applied 492 GC gc = new GC(fDescriptionText); 493 gc.setFont(fDescriptionText.getFont()); 494 FontMetrics metrics = gc.getFontMetrics(); 495 gc.dispose(); 496 int height = metrics.getHeight() * 5 / 2; 497 498 GridData gridData = new GridData(); 499 gridData.grabExcessHorizontalSpace = true; 500 gridData.horizontalAlignment = SWT.FILL; 501 gridData.horizontalSpan = 2; 502 gridData.heightHint = height; 503 fDescriptionText.setLayoutData(gridData); 504 505 return page; 506 } 507 508 /** 509 * Creates the button bar with "Filters..." and "Export CVS..." buttons. 510 * 511 * @param parent The composite in which the button bar should be placed; never 512 * <code>null</code>. 513 * @return The button bar composite; never <code>null</code>. 514 */ createButtonBar(final Composite parent)515 private final Control createButtonBar(final Composite parent) { 516 GridLayout layout; 517 GridData gridData; 518 int widthHint; 519 520 // Create the composite to house the button bar. 521 final Composite buttonBar = new Composite(parent, SWT.NONE); 522 layout = new GridLayout(2, false); 523 layout.marginWidth = 0; 524 buttonBar.setLayout(layout); 525 gridData = new GridData(); 526 gridData.horizontalAlignment = SWT.END; 527 gridData.grabExcessHorizontalSpace = true; 528 buttonBar.setLayoutData(gridData); 529 530 // Advanced button. 531 final Button filtersButton = new Button(buttonBar, SWT.PUSH); 532 gridData = new GridData(); 533 widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); 534 filtersButton.setText(NewKeysPreferenceMessages.FiltersButton_Text); 535 gridData.widthHint = Math.max(widthHint, filtersButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x) + 5; 536 filtersButton.setLayoutData(gridData); 537 filtersButton.addSelectionListener(widgetSelectedAdapter(e -> { 538 KeysPreferenceFiltersDialog dialog = new KeysPreferenceFiltersDialog(getShell()); 539 dialog.setFilterActionSet(fFilterActionSetContexts); 540 dialog.setFilterInternal(fFilterInternalContexts); 541 dialog.setFilterUncategorized(fFilteredTree.isFilteringCategories()); 542 if (dialog.open() == Window.OK) { 543 fFilterActionSetContexts = dialog.getFilterActionSet(); 544 fFilterInternalContexts = dialog.getFilterInternal(); 545 fFilteredTree.filterCategories(dialog.getFilterUncategorized()); 546 547 // Apply context filters 548 keyController.filterContexts(fFilterActionSetContexts, fFilterInternalContexts); 549 550 ISelection currentContextSelection = fWhenCombo.getSelection(); 551 fWhenCombo.setInput(keyController.getContextModel()); 552 fWhenCombo.setSelection(currentContextSelection); 553 } 554 })); 555 556 // Export bindings to CSV 557 final Button exportButton = new Button(buttonBar, SWT.PUSH); 558 // gridData = new GridData(); 559 widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); 560 exportButton.setText(NewKeysPreferenceMessages.ExportButton_Text); 561 gridData.widthHint = Math.max(widthHint, exportButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x) + 5; 562 exportButton.setLayoutData(gridData); 563 exportButton.addSelectionListener( 564 widgetSelectedAdapter(e -> keyController.exportCSV(((Button) e.getSource()).getShell()))); 565 566 return buttonBar; 567 } 568 createDataControls(final Composite parent)569 private final void createDataControls(final Composite parent) { 570 GridLayout layout; 571 GridData gridData; 572 573 // Creates the data area. 574 final Composite dataArea = new Composite(parent, SWT.NONE); 575 layout = new GridLayout(2, true); 576 layout.marginWidth = 0; 577 dataArea.setLayout(layout); 578 gridData = new GridData(); 579 gridData.grabExcessHorizontalSpace = true; 580 gridData.horizontalAlignment = SWT.FILL; 581 dataArea.setLayoutData(gridData); 582 583 // LEFT DATA AREA 584 // Creates the left data area. 585 final Composite leftDataArea = new Composite(dataArea, SWT.NONE); 586 layout = new GridLayout(3, false); 587 leftDataArea.setLayout(layout); 588 gridData = new GridData(); 589 gridData.grabExcessHorizontalSpace = true; 590 gridData.verticalAlignment = SWT.TOP; 591 gridData.horizontalAlignment = SWT.FILL; 592 leftDataArea.setLayoutData(gridData); 593 594 // The command name label. 595 final Label commandNameLabel = new Label(leftDataArea, SWT.NONE); 596 commandNameLabel.setText(NewKeysPreferenceMessages.CommandNameLabel_Text); 597 598 // The current command name. 599 commandNameValueLabel = new Label(leftDataArea, SWT.NONE); 600 gridData = new GridData(); 601 gridData.grabExcessHorizontalSpace = true; 602 gridData.horizontalSpan = 2; 603 gridData.horizontalAlignment = SWT.FILL; 604 commandNameValueLabel.setLayoutData(gridData); 605 606 final Label commandDescriptionlabel = new Label(leftDataArea, SWT.LEAD); 607 commandDescriptionlabel.setText(NewKeysPreferenceMessages.CommandDescriptionLabel_Text); 608 gridData = new GridData(); 609 gridData.verticalAlignment = SWT.BEGINNING; 610 commandDescriptionlabel.setLayoutData(gridData); 611 612 fDescriptionText = new Text(leftDataArea, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.READ_ONLY); 613 614 // The binding label. 615 final Label bindingLabel = new Label(leftDataArea, SWT.NONE); 616 bindingLabel.setText(NewKeysPreferenceMessages.BindingLabel_Text); 617 618 // The key sequence entry widget. 619 fBindingText = new Text(leftDataArea, SWT.BORDER); 620 gridData = new GridData(); 621 gridData.grabExcessHorizontalSpace = true; 622 gridData.horizontalAlignment = SWT.FILL; 623 gridData.widthHint = 200; 624 fBindingText.setLayoutData(gridData); 625 626 fBindingText.addFocusListener(new FocusListener() { 627 @Override 628 public void focusGained(FocusEvent e) { 629 fBindingService.setKeyFilterEnabled(false); 630 } 631 632 @Override 633 public void focusLost(FocusEvent e) { 634 fBindingService.setKeyFilterEnabled(true); 635 } 636 }); 637 fBindingText.addDisposeListener(e -> { 638 if (!fBindingService.isKeyFilterEnabled()) { 639 fBindingService.setKeyFilterEnabled(true); 640 } 641 }); 642 643 fKeySequenceText = new KeySequenceText(fBindingText); 644 fKeySequenceText.setKeyStrokeLimit(4); 645 fKeySequenceText.addPropertyChangeListener(event -> { 646 if (!event.getOldValue().equals(event.getNewValue())) { 647 final KeySequence keySequence = fKeySequenceText.getKeySequence(); 648 if (!keySequence.isComplete()) { 649 return; 650 } 651 652 BindingElement activeBinding = (BindingElement) keyController.getBindingModel().getSelectedElement(); 653 if (activeBinding != null) { 654 activeBinding.setTrigger(keySequence); 655 } 656 fBindingText.setSelection(fBindingText.getTextLimit()); 657 } 658 }); 659 660 // Button for adding trapped key strokes 661 final Button addKeyButton = new Button(leftDataArea, SWT.LEFT | SWT.ARROW); 662 addKeyButton.setToolTipText(NewKeysPreferenceMessages.AddKeyButton_ToolTipText); 663 gridData = new GridData(); 664 gridData.heightHint = fSchemeCombo.getCombo().getTextHeight(); 665 addKeyButton.setLayoutData(gridData); 666 667 // Arrow buttons aren't normally added to the tab list. Let's fix that. 668 final Control[] tabStops = dataArea.getTabList(); 669 final ArrayList<Control> newTabStops = new ArrayList<>(); 670 for (Control tabStop : tabStops) { 671 newTabStops.add(tabStop); 672 if (fBindingText.equals(tabStop)) { 673 newTabStops.add(addKeyButton); 674 } 675 } 676 final Control[] newTabStopArray = newTabStops.toArray(new Control[newTabStops.size()]); 677 dataArea.setTabList(newTabStopArray); 678 679 // Construct the menu to attach to the above button. 680 final Menu addKeyMenu = new Menu(addKeyButton); 681 final Iterator<KeyStroke> trappedKeyItr = KeySequenceText.TRAPPED_KEYS.iterator(); 682 while (trappedKeyItr.hasNext()) { 683 final KeyStroke trappedKey = trappedKeyItr.next(); 684 final MenuItem menuItem = new MenuItem(addKeyMenu, SWT.PUSH); 685 menuItem.setText(trappedKey.format()); 686 menuItem.addSelectionListener(widgetSelectedAdapter(e -> { 687 fKeySequenceText.insert(trappedKey); 688 fBindingText.setFocus(); 689 fBindingText.setSelection(fBindingText.getTextLimit()); 690 })); 691 } 692 addKeyButton.addSelectionListener(widgetSelectedAdapter(selectionEvent -> { 693 Point buttonLocation = addKeyButton.getLocation(); 694 buttonLocation = dataArea.toDisplay(buttonLocation.x, buttonLocation.y); 695 Point buttonSize = addKeyButton.getSize(); 696 addKeyMenu.setLocation(buttonLocation.x, buttonLocation.y + buttonSize.y); 697 addKeyMenu.setVisible(true); 698 })); 699 700 // The when label. 701 final Label whenLabel = new Label(leftDataArea, SWT.NONE); 702 whenLabel.setText(NewKeysPreferenceMessages.WhenLabel_Text); 703 704 // The when combo. 705 fWhenCombo = new ComboViewer(leftDataArea); 706 gridData = new GridData(); 707 gridData.grabExcessHorizontalSpace = true; 708 gridData.horizontalAlignment = SWT.FILL; 709 gridData.horizontalSpan = 2; 710 gridData.widthHint = 200; 711 ViewerComparator comparator = new ViewerComparator(); 712 fWhenCombo.setComparator(comparator); 713 fWhenCombo.getCombo().setLayoutData(gridData); 714 fWhenCombo.setContentProvider(new ModelContentProvider()); 715 fWhenCombo.setLabelProvider(new ListLabelProvider()); 716 fWhenCombo.addSelectionChangedListener(event -> { 717 ContextElement context = (ContextElement) event.getStructuredSelection().getFirstElement(); 718 if (context != null) { 719 keyController.getContextModel().setSelectedElement(context); 720 } 721 }); 722 IPropertyChangeListener whenListener = event -> { 723 if (event.getSource() == keyController.getContextModel() 724 && CommonModel.PROP_SELECTED_ELEMENT.equals(event.getProperty())) { 725 Object newVal = event.getNewValue(); 726 StructuredSelection structuredSelection = newVal == null ? null : new StructuredSelection(newVal); 727 fWhenCombo.setSelection(structuredSelection, true); 728 } 729 }; 730 keyController.addPropertyChangeListener(whenListener); 731 732 // RIGHT DATA AREA 733 // Creates the right data area. 734 final Composite rightDataArea = new Composite(dataArea, SWT.NONE); 735 layout = new GridLayout(1, false); 736 rightDataArea.setLayout(layout); 737 gridData = new GridData(SWT.FILL, SWT.FILL, true, true); 738 rightDataArea.setLayoutData(gridData); 739 740 new Label(rightDataArea, SWT.NONE); // filler 741 742 // The description label. 743 final Label descriptionLabel = new Label(rightDataArea, SWT.NONE); 744 descriptionLabel.setText(NewKeysPreferenceMessages.ConflictsLabel_Text); 745 gridData = new GridData(); 746 gridData.grabExcessHorizontalSpace = true; 747 gridData.horizontalAlignment = SWT.FILL; 748 descriptionLabel.setLayoutData(gridData); 749 750 conflictViewer = new TableViewer(rightDataArea, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); 751 Table table = conflictViewer.getTable(); 752 table.setHeaderVisible(true); 753 TableColumn bindingNameColumn = new TableColumn(table, SWT.LEAD); 754 bindingNameColumn.setText(NewKeysPreferenceMessages.CommandNameColumn_Text); 755 bindingNameColumn.setWidth(150); 756 TableColumn bindingContextNameColumn = new TableColumn(table, SWT.LEAD); 757 bindingContextNameColumn.setText(NewKeysPreferenceMessages.WhenColumn_Text); 758 bindingContextNameColumn.setWidth(150); 759 gridData = new GridData(SWT.FILL, SWT.FILL, true, true); 760 // gridData.horizontalIndent = 10; 761 table.setLayoutData(gridData); 762 TableLayout tableLayout = new TableLayout(); 763 tableLayout.addColumnData(new ColumnWeightData(60)); 764 tableLayout.addColumnData(new ColumnWeightData(40)); 765 table.setLayout(tableLayout); 766 conflictViewer.setContentProvider((IStructuredContentProvider) inputElement -> { 767 if (inputElement instanceof Collection<?>) { 768 return ((Collection<?>) inputElement).toArray(new Object[0]); 769 } 770 return new Object[0]; 771 }); 772 conflictViewer.setLabelProvider(new BindingElementLabelProvider() { 773 @Override 774 public String getColumnText(Object o, int index) { 775 BindingElement element = (BindingElement) o; 776 if (index == 0) { 777 return element.getName(); 778 } 779 return element.getContext().getName(); 780 } 781 }); 782 conflictViewer.addSelectionChangedListener(event -> { 783 ModelElement binding = (ModelElement) event.getStructuredSelection().getFirstElement(); 784 BindingModel bindingModel = keyController.getBindingModel(); 785 if (binding != null && binding != bindingModel.getSelectedElement()) { 786 StructuredSelection selection = new StructuredSelection(binding); 787 788 bindingModel.setSelectedElement(binding); 789 conflictViewer.setSelection(selection); 790 791 boolean selectionVisible = false; 792 TreeItem[] items = fFilteredTree.getViewer().getTree().getItems(); 793 for (TreeItem item : items) { 794 if (item.getData().equals(binding)) { 795 selectionVisible = true; 796 break; 797 } 798 } 799 800 if (!selectionVisible) { 801 fFilteredTree.getFilterControl().setText(""); //$NON-NLS-1$ 802 fFilteredTree.getViewer().refresh(); 803 bindingModel.setSelectedElement(binding); 804 conflictViewer.setSelection(selection); 805 } 806 } 807 }); 808 809 IPropertyChangeListener conflictsListener = event -> { 810 if (event.getSource() == keyController.getConflictModel() 811 && CommonModel.PROP_SELECTED_ELEMENT.equals(event.getProperty())) { 812 if (keyController.getConflictModel().getConflicts() != null) { 813 Object newVal = event.getNewValue(); 814 StructuredSelection structuredSelection = newVal == null ? null : new StructuredSelection(newVal); 815 conflictViewer.setSelection(structuredSelection, true); 816 } 817 } else if (ConflictModel.PROP_CONFLICTS.equals(event.getProperty())) { 818 conflictViewer.setInput(event.getNewValue()); 819 } else if (ConflictModel.PROP_CONFLICTS_ADD.equals(event.getProperty())) { 820 conflictViewer.add(event.getNewValue()); 821 } else if (ConflictModel.PROP_CONFLICTS_REMOVE.equals(event.getProperty())) { 822 conflictViewer.remove(event.getNewValue()); 823 } 824 }; 825 keyController.addPropertyChangeListener(conflictsListener); 826 827 IPropertyChangeListener dataUpdateListener = event -> { 828 BindingElement bindingElement = null; 829 boolean weCare = false; 830 if (event.getSource() == keyController.getBindingModel() 831 && CommonModel.PROP_SELECTED_ELEMENT.equals(event.getProperty())) { 832 bindingElement = (BindingElement) event.getNewValue(); 833 weCare = true; 834 } else if (event.getSource() == keyController.getBindingModel().getSelectedElement() 835 && ModelElement.PROP_MODEL_OBJECT.equals(event.getProperty())) { 836 bindingElement = (BindingElement) event.getSource(); 837 weCare = true; 838 } 839 if (bindingElement == null && weCare) { 840 commandNameValueLabel.setText(""); //$NON-NLS-1$ 841 fDescriptionText.setText(""); //$NON-NLS-1$ 842 fBindingText.setText(""); //$NON-NLS-1$ 843 } else if (bindingElement != null) { 844 commandNameValueLabel.setText(bindingElement.getName()); 845 String desc = bindingElement.getDescription(); 846 fDescriptionText.setText(desc == null ? "" : desc); //$NON-NLS-1$ 847 KeySequence trigger = (KeySequence) bindingElement.getTrigger(); 848 fKeySequenceText.setKeySequence(trigger); 849 } 850 }; 851 keyController.addPropertyChangeListener(dataUpdateListener); 852 853 } 854 createTree(Composite parent)855 private void createTree(Composite parent) { 856 fPatternFilter = new CategoryPatternFilter(true, fDefaultCategory); 857 fPatternFilter.filterCategories(true); 858 859 GridData gridData; 860 861 fFilteredTree = new CategoryFilterTree(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER, fPatternFilter); 862 final GridLayout layout = new GridLayout(1, false); 863 layout.marginWidth = 0; 864 fFilteredTree.setLayout(layout); 865 gridData = new GridData(); 866 gridData.grabExcessHorizontalSpace = true; 867 gridData.grabExcessVerticalSpace = true; 868 gridData.horizontalAlignment = SWT.FILL; 869 gridData.verticalAlignment = SWT.FILL; 870 fFilteredTree.setLayoutData(gridData); 871 872 final TreeViewer viewer = fFilteredTree.getViewer(); 873 // Make sure the filtered tree has a height of ITEMS_TO_SHOW 874 final Tree tree = viewer.getTree(); 875 tree.setHeaderVisible(true); 876 final Object layoutData = tree.getLayoutData(); 877 if (layoutData instanceof GridData) { 878 gridData = (GridData) layoutData; 879 final int itemHeight = tree.getItemHeight(); 880 if (itemHeight > 1) { 881 gridData.heightHint = ITEMS_TO_SHOW * itemHeight; 882 } 883 } 884 885 BindingModelComparator comparator = new BindingModelComparator(); 886 viewer.setComparator(comparator); 887 888 final TreeColumn commandNameColumn = new TreeColumn(tree, SWT.LEFT, COMMAND_NAME_COLUMN); 889 commandNameColumn.setText(NewKeysPreferenceMessages.CommandNameColumn_Text); 890 tree.setSortColumn(commandNameColumn); 891 tree.setSortDirection(comparator.isAscending() ? SWT.UP : SWT.DOWN); 892 commandNameColumn 893 .addSelectionListener(new ResortColumn(comparator, commandNameColumn, viewer, COMMAND_NAME_COLUMN)); 894 895 final TreeColumn triggerSequenceColumn = new TreeColumn(tree, SWT.LEFT, KEY_SEQUENCE_COLUMN); 896 triggerSequenceColumn.setText(NewKeysPreferenceMessages.TriggerSequenceColumn_Text); 897 triggerSequenceColumn 898 .addSelectionListener(new ResortColumn(comparator, triggerSequenceColumn, viewer, KEY_SEQUENCE_COLUMN)); 899 900 final TreeColumn whenColumn = new TreeColumn(tree, SWT.LEFT, CONTEXT_COLUMN); 901 whenColumn.setText(NewKeysPreferenceMessages.WhenColumn_Text); 902 whenColumn.addSelectionListener(new ResortColumn(comparator, whenColumn, viewer, CONTEXT_COLUMN)); 903 904 final TreeColumn categoryColumn = new TreeColumn(tree, SWT.LEFT, CATEGORY_COLUMN); 905 categoryColumn.setText(NewKeysPreferenceMessages.CategoryColumn_Text); 906 categoryColumn.addSelectionListener(new ResortColumn(comparator, categoryColumn, viewer, CATEGORY_COLUMN)); 907 908 final TreeColumn userMarker = new TreeColumn(tree, SWT.LEFT, USER_DELTA_COLUMN); 909 userMarker.setText(NewKeysPreferenceMessages.UserColumn_Text); 910 userMarker.addSelectionListener(new ResortColumn(comparator, userMarker, viewer, USER_DELTA_COLUMN)); 911 912 viewer.setContentProvider(new ModelContentProvider()); 913 viewer.setLabelProvider(new BindingElementLabelProvider()); 914 915 fFilteredTree.getPatternFilter().setIncludeLeadingWildcard(true); 916 final TreeColumn[] columns = viewer.getTree().getColumns(); 917 918 columns[COMMAND_NAME_COLUMN].setWidth(240); 919 columns[KEY_SEQUENCE_COLUMN].setWidth(130); 920 columns[CONTEXT_COLUMN].setWidth(130); 921 columns[CATEGORY_COLUMN].setWidth(130); 922 columns[USER_DELTA_COLUMN].setWidth(50); 923 924 viewer.addSelectionChangedListener(event -> { 925 ModelElement binding = (ModelElement) event.getStructuredSelection().getFirstElement(); 926 keyController.getBindingModel().setSelectedElement(binding); 927 }); 928 929 IPropertyChangeListener treeUpdateListener = event -> { 930 if (event.getSource() == keyController.getBindingModel() 931 && CommonModel.PROP_SELECTED_ELEMENT.equals(event.getProperty())) { 932 Object newVal = event.getNewValue(); 933 StructuredSelection structuredSelection = newVal == null ? null : new StructuredSelection(newVal); 934 viewer.setSelection(structuredSelection, true); 935 } else if (event.getSource() instanceof BindingElement 936 && ModelElement.PROP_MODEL_OBJECT.equals(event.getProperty())) { 937 viewer.update(event.getSource(), null); 938 } else if (BindingElement.PROP_CONFLICT.equals(event.getProperty())) { 939 viewer.update(event.getSource(), null); 940 } else if (BindingModel.PROP_BINDINGS.equals(event.getProperty())) { 941 viewer.refresh(); 942 } else if (BindingModel.PROP_BINDING_ADD.equals(event.getProperty())) { 943 viewer.add(keyController.getBindingModel(), event.getNewValue()); 944 } else if (BindingModel.PROP_BINDING_REMOVE.equals(event.getProperty())) { 945 viewer.remove(event.getNewValue()); 946 } else if (BindingModel.PROP_BINDING_FILTER.equals(event.getProperty())) { 947 viewer.refresh(); 948 } 949 }; 950 keyController.addPropertyChangeListener(treeUpdateListener); 951 // as far as I got 952 } 953 createTreeControls(final Composite parent)954 private final Control createTreeControls(final Composite parent) { 955 GridLayout layout; 956 GridData gridData; 957 int widthHint; 958 959 // Creates controls related to the tree. 960 final Composite treeControls = new Composite(parent, SWT.NONE); 961 layout = new GridLayout(4, false); 962 layout.marginWidth = 0; 963 treeControls.setLayout(layout); 964 gridData = new GridData(); 965 gridData.grabExcessHorizontalSpace = true; 966 gridData.horizontalAlignment = SWT.FILL; 967 treeControls.setLayoutData(gridData); 968 969 final Button addBindingButton = new Button(treeControls, SWT.PUSH); 970 gridData = new GridData(); 971 widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); 972 addBindingButton.setText(NewKeysPreferenceMessages.AddBindingButton_Text); 973 gridData.widthHint = Math.max(widthHint, addBindingButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x) + 5; 974 addBindingButton.setLayoutData(gridData); 975 addBindingButton.addSelectionListener(widgetSelectedAdapter(event -> keyController.getBindingModel().copy())); 976 977 final Button removeBindingButton = new Button(treeControls, SWT.PUSH); 978 gridData = new GridData(); 979 widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); 980 removeBindingButton.setText(NewKeysPreferenceMessages.RemoveBindingButton_Text); 981 gridData.widthHint = Math.max(widthHint, removeBindingButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x) + 5; 982 removeBindingButton.setLayoutData(gridData); 983 removeBindingButton 984 .addSelectionListener(widgetSelectedAdapter(event -> keyController.getBindingModel().remove())); 985 986 final Button restore = new Button(treeControls, SWT.PUSH); 987 gridData = new GridData(); 988 widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); 989 restore.setText(NewKeysPreferenceMessages.RestoreBindingButton_Text); 990 gridData.widthHint = Math.max(widthHint, restore.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x) + 5; 991 restore.setLayoutData(gridData); 992 restore.addSelectionListener(widgetSelectedAdapter(event -> { 993 try { 994 fFilteredTree.setRedraw(false); 995 BindingModel bindingModel = keyController.getBindingModel(); 996 bindingModel.restoreBinding(keyController.getContextModel()); 997 } finally { 998 fFilteredTree.setRedraw(true); 999 } 1000 })); 1001 1002 createButtonBar(treeControls); 1003 return treeControls; 1004 } 1005 1006 /** 1007 * 1008 */ fill()1009 private void fill() { 1010 fSchemeCombo.setInput(keyController.getSchemeModel()); 1011 fSchemeCombo.setSelection(new StructuredSelection(keyController.getSchemeModel().getSelectedElement())); 1012 1013 // Apply context filters 1014 keyController.filterContexts(fFilterActionSetContexts, fFilterInternalContexts); 1015 fWhenCombo.setInput(keyController.getContextModel()); 1016 1017 fFilteredTree.filterCategories(fPatternFilter.isFilteringCategories()); 1018 fFilteredTree.getViewer().setInput(keyController.getBindingModel()); 1019 } 1020 createSchemeControls(Composite parent)1021 private void createSchemeControls(Composite parent) { 1022 final Composite schemeControls = new Composite(parent, SWT.NONE); 1023 GridLayout layout = new GridLayout(3, false); 1024 layout.marginWidth = 0; 1025 schemeControls.setLayout(layout); 1026 1027 final Label schemeLabel = new Label(schemeControls, SWT.NONE); 1028 schemeLabel.setText(NewKeysPreferenceMessages.SchemeLabel_Text); 1029 1030 fSchemeCombo = new ComboViewer(schemeControls); 1031 fSchemeCombo.setLabelProvider(new ListLabelProvider()); 1032 fSchemeCombo.setContentProvider(new ModelContentProvider()); 1033 GridData gridData = new GridData(); 1034 gridData.widthHint = 150; 1035 gridData.horizontalAlignment = SWT.FILL; 1036 fSchemeCombo.getCombo().setLayoutData(gridData); 1037 fSchemeCombo.addSelectionChangedListener( 1038 event -> BusyIndicator.showWhile(fFilteredTree.getViewer().getTree().getDisplay(), () -> { 1039 SchemeElement scheme = (SchemeElement) event.getStructuredSelection().getFirstElement(); 1040 keyController.getSchemeModel().setSelectedElement(scheme); 1041 })); 1042 IPropertyChangeListener listener = event -> { 1043 if (event.getSource() == keyController.getSchemeModel() 1044 && CommonModel.PROP_SELECTED_ELEMENT.equals(event.getProperty())) { 1045 Object newVal = event.getNewValue(); 1046 StructuredSelection structuredSelection = newVal == null ? null : new StructuredSelection(newVal); 1047 fSchemeCombo.setSelection(structuredSelection, true); 1048 } 1049 }; 1050 1051 keyController.addPropertyChangeListener(listener); 1052 } 1053 createShowKeysControls(Composite parent)1054 private void createShowKeysControls(Composite parent) { 1055 ShowKeysUI showKeysUI = new ShowKeysUI(fWorkbench, getPreferenceStore()); 1056 1057 final Group group = new Group(parent, SWT.NONE); 1058 group.setText(NewKeysPreferenceMessages.ShowCommandKeysGroup_Title); 1059 group.setLayout(new GridLayout(1, false)); 1060 group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); 1061 1062 fShowCommandKey = new Button(group, SWT.CHECK); 1063 fShowCommandKey.setText(NewKeysPreferenceMessages.ShowCommandKeysForKeyboard_Text); 1064 fShowCommandKey.setSelection(getPreferenceStore().getBoolean(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_KEYBOARD)); 1065 fShowCommandKey.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { 1066 // show a preview of the shortcut popup 1067 if (fShowCommandKey.getSelection()) { 1068 showKeysUI.openForPreview(ShowKeysToggleHandler.COMMAND_ID, null); 1069 } 1070 })); 1071 fShowCommandKeyForMouseEvents = new Button(group, SWT.CHECK); 1072 fShowCommandKeyForMouseEvents.setText(NewKeysPreferenceMessages.ShowCommandKeysForMouse_Text); 1073 fShowCommandKeyForMouseEvents 1074 .setSelection(getPreferenceStore().getBoolean(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_MOUSE_EVENTS)); 1075 fShowCommandKeyForMouseEvents.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { 1076 // show a preview of the shortcut popup 1077 if (fShowCommandKeyForMouseEvents.getSelection()) { 1078 showKeysUI.openForPreview(ShowKeysToggleHandler.COMMAND_ID, null); 1079 } 1080 })); 1081 } 1082 1083 @Override init(IWorkbench workbench)1084 public void init(IWorkbench workbench) { 1085 fWorkbench = workbench; 1086 keyController = new KeyController(); 1087 keyController.init(workbench); 1088 1089 commandService = workbench.getService(ICommandService.class); 1090 fDefaultCategory = commandService.getCategory(null); 1091 fBindingService = workbench.getService(IBindingService.class); 1092 1093 commandImageService = workbench.getService(ICommandImageService.class); 1094 } 1095 1096 @Override applyData(Object data)1097 public void applyData(Object data) { 1098 if (data instanceof ModelElement) { 1099 keyController.getBindingModel().setSelectedElement((ModelElement) data); 1100 } 1101 if (data instanceof Binding && fFilteredTree != null) { 1102 BindingElement be = keyController.getBindingModel().getBindingToElement().get(data); 1103 fFilteredTree.getViewer().setSelection(new StructuredSelection(be), true); 1104 } 1105 if (data instanceof ParameterizedCommand) { 1106 Map<ParameterizedCommand, BindingElement> commandToElement = keyController.getBindingModel().getCommandToElement(); 1107 1108 BindingElement be = commandToElement.get(data); 1109 if (be != null) { 1110 fFilteredTree.getViewer().setSelection(new StructuredSelection(be), true); 1111 } 1112 } 1113 } 1114 1115 @Override performOk()1116 public boolean performOk() { 1117 keyController.saveBindings(fBindingService); 1118 IPreferenceStore preferenceStore = getPreferenceStore(); 1119 preferenceStore.setValue(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_KEYBOARD, fShowCommandKey.getSelection()); 1120 preferenceStore.setValue(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_MOUSE_EVENTS, 1121 fShowCommandKeyForMouseEvents.getSelection()); 1122 1123 saveState(getDialogSettings()); 1124 return super.performOk(); 1125 } 1126 1127 @Override doGetPreferenceStore()1128 protected IPreferenceStore doGetPreferenceStore() { 1129 return WorkbenchPlugin.getDefault().getPreferenceStore(); 1130 } 1131 1132 /** 1133 * Save the state of the receiver. 1134 * 1135 * @param dialogSettings 1136 */ saveState(IDialogSettings dialogSettings)1137 public void saveState(IDialogSettings dialogSettings) { 1138 if (dialogSettings == null) { 1139 return; 1140 } 1141 dialogSettings.put(TAG_FILTER_ACTION_SETS, fFilterActionSetContexts); 1142 dialogSettings.put(TAG_FILTER_INTERNAL, fFilterInternalContexts); 1143 dialogSettings.put(TAG_FILTER_UNCAT, fFilteredTree.isFilteringCategories()); 1144 } 1145 getDialogSettings()1146 protected IDialogSettings getDialogSettings() { 1147 IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault().getDialogSettings(); 1148 1149 IDialogSettings settings = workbenchSettings.getSection(TAG_DIALOG_SECTION); 1150 1151 if (settings == null) { 1152 settings = workbenchSettings.addNewSection(TAG_DIALOG_SECTION); 1153 } 1154 return settings; 1155 } 1156 1157 @Override performDefaults()1158 protected final void performDefaults() { 1159 1160 // Ask the user to confirm 1161 final String title = NewKeysPreferenceMessages.RestoreDefaultsMessageBoxText; 1162 final String message = NewKeysPreferenceMessages.RestoreDefaultsMessageBoxMessage; 1163 final boolean confirmed = MessageDialog.open(MessageDialog.CONFIRM, getShell(), title, message, SWT.SHEET); 1164 1165 if (confirmed) { 1166 long startTime = 0L; 1167 if (DEBUG) { 1168 startTime = System.currentTimeMillis(); 1169 } 1170 1171 fFilteredTree.setRedraw(false); 1172 BusyIndicator.showWhile(fFilteredTree.getViewer().getTree().getDisplay(), 1173 () -> keyController.setDefaultBindings(fBindingService)); 1174 fFilteredTree.setRedraw(true); 1175 if (DEBUG) { 1176 final long elapsedTime = System.currentTimeMillis() - startTime; 1177 Tracing.printTrace(TRACING_COMPONENT, "performDefaults:model in " + elapsedTime + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ 1178 1179 } 1180 1181 fShowCommandKey 1182 .setSelection(getPreferenceStore().getDefaultBoolean(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_KEYBOARD)); 1183 fShowCommandKeyForMouseEvents.setSelection( 1184 getPreferenceStore().getDefaultBoolean(IPreferenceConstants.SHOW_KEYS_ENABLED_FOR_MOUSE_EVENTS)); 1185 } 1186 1187 super.performDefaults(); 1188 } 1189 } 1190