1 11 package org.eclipse.ui.dialogs; 12 13 import java.io.IOException ; 14 import java.io.StringReader ; 15 import java.io.StringWriter ; 16 import java.util.ArrayList ; 17 import java.util.Arrays ; 18 import java.util.Collections ; 19 import java.util.Comparator ; 20 import java.util.HashMap ; 21 import java.util.HashSet ; 22 import java.util.Iterator ; 23 import java.util.LinkedList ; 24 import java.util.List ; 25 import java.util.Set ; 26 27 import org.eclipse.core.runtime.Assert; 28 import org.eclipse.core.runtime.CoreException; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.IStatus; 31 import org.eclipse.core.runtime.ListenerList; 32 import org.eclipse.core.runtime.ProgressMonitorWrapper; 33 import org.eclipse.core.runtime.Status; 34 import org.eclipse.core.runtime.SubProgressMonitor; 35 import org.eclipse.core.runtime.jobs.Job; 36 import org.eclipse.jface.action.Action; 37 import org.eclipse.jface.action.ActionContributionItem; 38 import org.eclipse.jface.action.IAction; 39 import org.eclipse.jface.action.IMenuListener; 40 import org.eclipse.jface.action.IMenuManager; 41 import org.eclipse.jface.action.MenuManager; 42 import org.eclipse.jface.dialogs.IDialogSettings; 43 import org.eclipse.jface.viewers.ContentViewer; 44 import org.eclipse.jface.viewers.DoubleClickEvent; 45 import org.eclipse.jface.viewers.IColorProvider; 46 import org.eclipse.jface.viewers.IContentProvider; 47 import org.eclipse.jface.viewers.IDoubleClickListener; 48 import org.eclipse.jface.viewers.IFontProvider; 49 import org.eclipse.jface.viewers.ILabelDecorator; 50 import org.eclipse.jface.viewers.ILabelProvider; 51 import org.eclipse.jface.viewers.ILabelProviderListener; 52 import org.eclipse.jface.viewers.ILazyContentProvider; 53 import org.eclipse.jface.viewers.ISelection; 54 import org.eclipse.jface.viewers.ISelectionChangedListener; 55 import org.eclipse.jface.viewers.IStructuredContentProvider; 56 import org.eclipse.jface.viewers.LabelProvider; 57 import org.eclipse.jface.viewers.LabelProviderChangedEvent; 58 import org.eclipse.jface.viewers.SelectionChangedEvent; 59 import org.eclipse.jface.viewers.StructuredSelection; 60 import org.eclipse.jface.viewers.TableViewer; 61 import org.eclipse.jface.viewers.Viewer; 62 import org.eclipse.jface.viewers.ViewerFilter; 63 import org.eclipse.osgi.util.NLS; 64 import org.eclipse.swt.SWT; 65 import org.eclipse.swt.custom.CLabel; 66 import org.eclipse.swt.custom.ViewForm; 67 import org.eclipse.swt.events.KeyAdapter; 68 import org.eclipse.swt.events.KeyEvent; 69 import org.eclipse.swt.events.ModifyEvent; 70 import org.eclipse.swt.events.ModifyListener; 71 import org.eclipse.swt.events.MouseAdapter; 72 import org.eclipse.swt.events.MouseEvent; 73 import org.eclipse.swt.events.SelectionAdapter; 74 import org.eclipse.swt.events.SelectionEvent; 75 import org.eclipse.swt.events.TraverseEvent; 76 import org.eclipse.swt.events.TraverseListener; 77 import org.eclipse.swt.graphics.Color; 78 import org.eclipse.swt.graphics.Font; 79 import org.eclipse.swt.graphics.GC; 80 import org.eclipse.swt.graphics.Image; 81 import org.eclipse.swt.graphics.Point; 82 import org.eclipse.swt.graphics.Rectangle; 83 import org.eclipse.swt.layout.GridData; 84 import org.eclipse.swt.layout.GridLayout; 85 import org.eclipse.swt.widgets.Composite; 86 import org.eclipse.swt.widgets.Control; 87 import org.eclipse.swt.widgets.Display; 88 import org.eclipse.swt.widgets.Event; 89 import org.eclipse.swt.widgets.Label; 90 import org.eclipse.swt.widgets.Menu; 91 import org.eclipse.swt.widgets.Shell; 92 import org.eclipse.swt.widgets.Text; 93 import org.eclipse.swt.widgets.ToolBar; 94 import org.eclipse.swt.widgets.ToolItem; 95 import org.eclipse.ui.IMemento; 96 import org.eclipse.ui.PlatformUI; 97 import org.eclipse.ui.WorkbenchException; 98 import org.eclipse.ui.XMLMemento; 99 import org.eclipse.ui.internal.IWorkbenchGraphicConstants; 100 import org.eclipse.ui.internal.WorkbenchImages; 101 import org.eclipse.ui.internal.WorkbenchMessages; 102 import org.eclipse.ui.internal.WorkbenchPlugin; 103 import org.eclipse.ui.progress.UIJob; 104 import org.eclipse.ui.statushandlers.StatusManager; 105 106 112 public abstract class FilteredItemsSelectionDialog extends 113 SelectionStatusDialog { 114 115 private static final String DIALOG_BOUNDS_SETTINGS = "DialogBoundsSettings"; 117 private static final String SHOW_STATUS_LINE = "ShowStatusLine"; 119 private static final String HISTORY_SETTINGS = "History"; 121 private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; 123 private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; 125 129 public static final int NONE = 0; 130 131 135 public static final int CARET_BEGINNING = 1; 136 137 141 public static final int FULL_SELECTION = 2; 142 143 private Text pattern; 144 145 private TableViewer list; 146 147 private DetailsContentViewer details; 148 149 154 private ILabelProvider detailsLabelProvider; 155 156 private ItemsListLabelProvider itemsListLabelProvider; 157 158 private MenuManager menuManager; 159 160 private boolean multi; 161 162 private ToolBar toolBar; 163 164 private ToolItem toolItem; 165 166 private Label progressLabel; 167 168 private ToggleStatusLineAction toggleStatusLineAction; 169 170 private RemoveHistoryItemAction removeHistoryItemAction; 171 172 private ActionContributionItem removeHistoryActionContributionItem; 173 174 private IStatus status; 175 176 private RefreshCacheJob refreshCacheJob; 177 178 private RefreshProgressMessageJob refreshProgressMessageJob = new RefreshProgressMessageJob(); 179 180 private Object [] lastSelection; 181 182 private ContentProvider contentProvider; 183 184 private FilterHistoryJob filterHistoryJob; 185 186 private FilterJob filterJob; 187 188 private ItemsFilter filter; 189 190 private List lastCompletedResult; 191 192 private ItemsFilter lastCompletedFilter; 193 194 private String initialPatternText; 195 196 private int selectionMode; 197 198 private ItemsListSeparator itemsListSeparator; 199 200 private static final String EMPTY_STRING = ""; 202 private boolean refreshWithLastSelection = false; 203 204 213 public FilteredItemsSelectionDialog(Shell shell, boolean multi) { 214 super(shell); 215 setShellStyle(getShellStyle() | SWT.RESIZE); 216 this.multi = multi; 217 filterHistoryJob = new FilterHistoryJob(); 218 filterJob = new FilterJob(); 219 contentProvider = new ContentProvider(); 220 refreshCacheJob = new RefreshCacheJob(); 221 itemsListSeparator = new ItemsListSeparator( 222 WorkbenchMessages.FilteredItemsSelectionDialog_separatorLabel); 223 selectionMode = NONE; 224 } 225 226 233 public FilteredItemsSelectionDialog(Shell shell) { 234 this(shell, false); 235 } 236 237 243 protected void addListFilter(ViewerFilter filter) { 244 contentProvider.addFilter(filter); 245 } 246 247 253 public void setListLabelProvider(ILabelProvider listLabelProvider) { 254 getItemsListLabelProvider().setProvider(listLabelProvider); 255 } 256 257 262 private ILabelDecorator getListSelectionLabelDecorator() { 263 return getItemsListLabelProvider().getSelectionDecorator(); 264 } 265 266 272 public void setListSelectionLabelDecorator( 273 ILabelDecorator listSelectionLabelDecorator) { 274 getItemsListLabelProvider().setSelectionDecorator( 275 listSelectionLabelDecorator); 276 } 277 278 283 private ItemsListLabelProvider getItemsListLabelProvider() { 284 if (itemsListLabelProvider == null) { 285 itemsListLabelProvider = new ItemsListLabelProvider( 286 new LabelProvider(), null); 287 } 288 return itemsListLabelProvider; 289 } 290 291 306 public void setDetailsLabelProvider(ILabelProvider detailsLabelProvider) { 307 this.detailsLabelProvider = detailsLabelProvider; 308 if (details != null) { 309 details.setLabelProvider(detailsLabelProvider); 310 } 311 } 312 313 private ILabelProvider getDetailsLabelProvider() { 314 if (detailsLabelProvider == null) { 315 detailsLabelProvider = new LabelProvider(); 316 } 317 return detailsLabelProvider; 318 } 319 320 325 public void create() { 326 super.create(); 327 pattern.setFocus(); 328 } 329 330 337 protected void restoreDialog(IDialogSettings settings) { 338 boolean toggleStatusLine = true; 339 340 if (settings.get(SHOW_STATUS_LINE) != null) { 341 toggleStatusLine = settings.getBoolean(SHOW_STATUS_LINE); 342 } 343 344 toggleStatusLineAction.setChecked(toggleStatusLine); 345 346 details.setVisible(toggleStatusLine); 347 348 String setting = settings.get(HISTORY_SETTINGS); 349 if (setting != null) { 350 try { 351 IMemento memento = XMLMemento.createReadRoot(new StringReader ( 352 setting)); 353 this.contentProvider.loadHistory(memento); 354 } catch (WorkbenchException e) { 355 StatusManager 357 .getManager() 358 .handle( 359 new Status( 360 IStatus.ERROR, 361 PlatformUI.PLUGIN_ID, 362 IStatus.ERROR, 363 WorkbenchMessages.FilteredItemsSelectionDialog_restoreError, 364 e)); 365 } 366 } 367 } 368 369 374 public boolean close() { 375 this.filterJob.cancel(); 376 this.refreshCacheJob.cancel(); 377 this.refreshProgressMessageJob.cancel(); 378 storeDialog(getDialogSettings()); 379 return super.close(); 380 } 381 382 388 protected void storeDialog(IDialogSettings settings) { 389 settings.put(SHOW_STATUS_LINE, toggleStatusLineAction.isChecked()); 390 391 XMLMemento memento = XMLMemento.createWriteRoot(HISTORY_SETTINGS); 392 this.contentProvider.saveHistory(memento); 393 StringWriter writer = new StringWriter (); 394 try { 395 memento.save(writer); 396 settings.put(HISTORY_SETTINGS, writer.getBuffer().toString()); 397 } catch (IOException e) { 398 StatusManager 400 .getManager() 401 .handle( 402 new Status( 403 IStatus.ERROR, 404 PlatformUI.PLUGIN_ID, 405 IStatus.ERROR, 406 WorkbenchMessages.FilteredItemsSelectionDialog_storeError, 407 e)); 408 } 409 } 410 411 private void createHeader(Composite parent) { 412 Composite header = new Composite(parent, SWT.NONE); 413 414 GridLayout layout = new GridLayout(); 415 layout.numColumns = 2; 416 layout.marginWidth = 0; 417 layout.marginHeight = 0; 418 header.setLayout(layout); 419 420 Label label = new Label(header, SWT.NONE); 421 label 422 .setText((getMessage() != null && getMessage().trim().length() > 0) ? getMessage() 423 : WorkbenchMessages.FilteredItemsSelectionDialog_patternLabel); 424 label.addTraverseListener(new TraverseListener() { 425 public void keyTraversed(TraverseEvent e) { 426 if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) { 427 e.detail = SWT.TRAVERSE_NONE; 428 pattern.setFocus(); 429 } 430 } 431 }); 432 433 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 434 label.setLayoutData(gd); 435 436 createViewMenu(header); 437 header.setLayoutData(gd); 438 } 439 440 private void createLabels(Composite parent) { 441 Composite labels = new Composite(parent, SWT.NONE); 442 443 GridLayout layout = new GridLayout(); 444 layout.numColumns = 2; 445 layout.marginWidth = 0; 446 layout.marginHeight = 0; 447 labels.setLayout(layout); 448 449 Label listLabel = new Label(labels, SWT.NONE); 450 listLabel 451 .setText(WorkbenchMessages.FilteredItemsSelectionDialog_listLabel); 452 453 listLabel.addTraverseListener(new TraverseListener() { 454 public void keyTraversed(TraverseEvent e) { 455 if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) { 456 e.detail = SWT.TRAVERSE_NONE; 457 list.getTable().setFocus(); 458 } 459 } 460 }); 461 462 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 463 listLabel.setLayoutData(gd); 464 465 progressLabel = new Label(labels, SWT.RIGHT); 466 progressLabel.setLayoutData(gd); 467 468 labels.setLayoutData(gd); 469 } 470 471 private void createViewMenu(Composite parent) { 472 toolBar = new ToolBar(parent, SWT.FLAT); 473 toolItem = new ToolItem(toolBar, SWT.PUSH, 0); 474 475 GridData data = new GridData(); 476 data.horizontalAlignment = GridData.END; 477 toolBar.setLayoutData(data); 478 479 toolBar.addMouseListener(new MouseAdapter() { 480 public void mouseDown(MouseEvent e) { 481 showViewMenu(); 482 } 483 }); 484 485 toolItem.setImage(WorkbenchImages 486 .getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU)); 487 toolItem 488 .setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu); 489 toolItem.addSelectionListener(new SelectionAdapter() { 490 public void widgetSelected(SelectionEvent e) { 491 showViewMenu(); 492 } 493 }); 494 495 menuManager = new MenuManager(); 496 497 fillViewMenu(menuManager); 498 } 499 500 506 protected void fillViewMenu(IMenuManager menuManager) { 507 toggleStatusLineAction = new ToggleStatusLineAction(); 508 menuManager.add(toggleStatusLineAction); 509 } 510 511 private void showViewMenu() { 512 Menu menu = menuManager.createContextMenu(getShell()); 513 Rectangle bounds = toolItem.getBounds(); 514 Point topLeft = new Point(bounds.x, bounds.y + bounds.height); 515 topLeft = toolBar.toDisplay(topLeft); 516 menu.setLocation(topLeft.x, topLeft.y); 517 menu.setVisible(true); 518 } 519 520 private void createPopupMenu() { 521 removeHistoryItemAction = new RemoveHistoryItemAction(); 522 removeHistoryActionContributionItem = new ActionContributionItem( 523 removeHistoryItemAction); 524 525 MenuManager manager = new MenuManager(); 526 manager.add(removeHistoryActionContributionItem); 527 manager.addMenuListener(new IMenuListener() { 528 public void menuAboutToShow(IMenuManager manager) { 529 List selectedElements = ((StructuredSelection) list 530 .getSelection()).toList(); 531 532 Object item = null; 533 534 manager.remove(removeHistoryActionContributionItem); 535 536 for (Iterator it = selectedElements.iterator(); it.hasNext();) { 537 item = it.next(); 538 if (item instanceof ItemsListSeparator 539 || !isHistoryElement(item)) { 540 return; 541 } 542 } 543 544 if (selectedElements.size() > 0) { 545 removeHistoryItemAction 546 .setText(WorkbenchMessages.FilteredItemsSelectionDialog_removeItemsFromHistoryAction); 547 548 manager.add(removeHistoryActionContributionItem); 549 550 } 551 } 552 }); 553 554 Menu menu = manager.createContextMenu(getShell()); 555 list.getTable().setMenu(menu); 556 } 557 558 565 protected abstract Control createExtendedContentArea(Composite parent); 566 567 572 protected Control createDialogArea(Composite parent) { 573 Composite dialogArea = (Composite) super.createDialogArea(parent); 574 575 Composite content = new Composite(dialogArea, SWT.NONE); 576 GridData gd = new GridData(GridData.FILL_BOTH); 577 content.setLayoutData(gd); 578 579 GridLayout layout = new GridLayout(); 580 layout.numColumns = 1; 581 layout.marginWidth = 0; 582 layout.marginHeight = 0; 583 content.setLayout(layout); 584 585 createHeader(content); 586 587 pattern = new Text(content, SWT.SINGLE | SWT.BORDER); 588 gd = new GridData(GridData.FILL_HORIZONTAL); 589 pattern.setLayoutData(gd); 590 591 createLabels(content); 592 593 list = new TableViewer(content, (multi ? SWT.MULTI : SWT.SINGLE) 594 | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL); 595 list.setContentProvider(contentProvider); 596 list.setLabelProvider(getItemsListLabelProvider()); 597 list.setInput(new Object [0]); 598 list.setItemCount(contentProvider.getElements(null).length); 599 gd = new GridData(GridData.FILL_BOTH); 600 list.getTable().setLayoutData(gd); 601 602 createPopupMenu(); 603 604 pattern.addModifyListener(new ModifyListener() { 605 public void modifyText(ModifyEvent e) { 606 applyFilter(); 607 } 608 }); 609 610 pattern.addKeyListener(new KeyAdapter() { 611 public void keyPressed(KeyEvent e) { 612 if (e.keyCode == SWT.ARROW_DOWN) { 613 if (list.getTable().getItemCount() > 0) { 614 list.getTable().setFocus(); 615 } 616 } 617 } 618 }); 619 620 list.addSelectionChangedListener(new ISelectionChangedListener() { 621 public void selectionChanged(SelectionChangedEvent event) { 622 StructuredSelection selection = (StructuredSelection) event 623 .getSelection(); 624 handleSelected(selection); 625 } 626 }); 627 628 list.addDoubleClickListener(new IDoubleClickListener() { 629 public void doubleClick(DoubleClickEvent event) { 630 handleDoubleClick(); 631 } 632 }); 633 634 list.getTable().addKeyListener(new KeyAdapter() { 635 public void keyPressed(KeyEvent e) { 636 637 if (e.keyCode == SWT.DEL) { 638 639 List selectedElements = ((StructuredSelection) list 640 .getSelection()).toList(); 641 642 Object item = null; 643 boolean isSelectedHistory = true; 644 645 for (Iterator it = selectedElements.iterator(); it 646 .hasNext();) { 647 item = it.next(); 648 if (item instanceof ItemsListSeparator 649 || !isHistoryElement(item)) { 650 isSelectedHistory = false; 651 break; 652 } 653 } 654 if (isSelectedHistory) 655 removeSelectedItems(selectedElements); 656 657 } 658 659 if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) != 0 660 && (e.stateMask & SWT.CTRL) != 0) { 661 StructuredSelection selection = (StructuredSelection) list 662 .getSelection(); 663 664 if (selection.size() == 1) { 665 Object element = selection.getFirstElement(); 666 if (element.equals(list.getElementAt(0))) { 667 pattern.setFocus(); 668 } 669 if (list.getElementAt(list.getTable() 670 .getSelectionIndex() - 1) instanceof ItemsListSeparator) 671 list.getTable().setSelection( 672 list.getTable().getSelectionIndex() - 1); 673 list.getTable().notifyListeners(SWT.Selection, 674 new Event()); 675 676 } 677 } 678 679 if (e.keyCode == SWT.ARROW_DOWN 680 && (e.stateMask & SWT.SHIFT) != 0 681 && (e.stateMask & SWT.CTRL) != 0) { 682 683 if (list 684 .getElementAt(list.getTable().getSelectionIndex() + 1) instanceof ItemsListSeparator) 685 list.getTable().setSelection( 686 list.getTable().getSelectionIndex() + 1); 687 list.getTable().notifyListeners(SWT.Selection, new Event()); 688 } 689 690 } 691 }); 692 693 createExtendedContentArea(content); 694 695 details = new DetailsContentViewer(content, SWT.BORDER | SWT.FLAT); 696 details.setVisible(toggleStatusLineAction.isChecked()); 697 details.setContentProvider(new NullContentProvider()); 698 details.setLabelProvider(getDetailsLabelProvider()); 699 700 applyDialogFont(content); 701 702 restoreDialog(getDialogSettings()); 703 704 if (initialPatternText != null) { 705 pattern.setText(initialPatternText); 706 } 707 708 switch (selectionMode) { 709 case CARET_BEGINNING: 710 pattern.setSelection(0, 0); 711 break; 712 case FULL_SELECTION: 713 pattern.setSelection(0, initialPatternText.length()); 714 break; 715 } 716 717 applyFilter(); 719 720 return dialogArea; 721 } 722 723 731 protected void handleDoubleClick() { 732 okPressed(); 733 } 734 735 739 private void refreshDetails() { 740 StructuredSelection selection = getSelectedItems(); 741 742 switch (selection.size()) { 743 case 0: 744 details.setInput(null); 745 break; 746 case 1: 747 details.setInput(selection.getFirstElement()); 748 break; 749 default: 750 details 751 .setInput(NLS 752 .bind( 753 WorkbenchMessages.FilteredItemsSelectionDialog_nItemsSelected, 754 new Integer (selection.size()))); 755 break; 756 } 757 758 } 759 760 767 protected void handleSelected(StructuredSelection selection) { 768 IStatus status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 769 IStatus.OK, EMPTY_STRING, null); 770 771 if (selection.size() == 0) { 772 status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 773 IStatus.ERROR, EMPTY_STRING, null); 774 775 if (lastSelection != null 776 && getListSelectionLabelDecorator() != null) { 777 list.update(lastSelection, null); 778 } 779 780 lastSelection = null; 781 782 } else { 783 status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 784 IStatus.ERROR, EMPTY_STRING, null); 785 786 List items = selection.toList(); 787 788 Object item = null; 789 IStatus tempStatus = null; 790 791 for (Iterator it = items.iterator(); it.hasNext();) { 792 Object o = it.next(); 793 794 if (o instanceof ItemsListSeparator) { 795 continue; 796 } 797 798 item = o; 799 tempStatus = validateItem(item); 800 801 if (tempStatus.isOK()) { 802 status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID, 803 IStatus.OK, EMPTY_STRING, null); 804 } else { 805 status = tempStatus; 806 break; 809 } 810 } 811 812 if (lastSelection != null 813 && getListSelectionLabelDecorator() != null) { 814 list.update(lastSelection, null); 815 } 816 817 if (getListSelectionLabelDecorator() != null) { 818 list.update(items.toArray(), null); 819 } 820 821 lastSelection = items.toArray(); 822 } 823 824 refreshDetails(); 825 updateStatus(status); 826 } 827 828 833 protected IDialogSettings getDialogBoundsSettings() { 834 IDialogSettings settings = getDialogSettings(); 835 IDialogSettings section = settings.getSection(DIALOG_BOUNDS_SETTINGS); 836 if (section == null) { 837 section = settings.addNewSection(DIALOG_BOUNDS_SETTINGS); 838 section.put(DIALOG_HEIGHT, 500); 839 section.put(DIALOG_WIDTH, 600); 840 } 841 return section; 842 } 843 844 849 protected abstract IDialogSettings getDialogSettings(); 850 851 854 public void refresh() { 855 if (list != null && !list.getTable().isDisposed()) { 856 857 List lastRefreshSelection = ((StructuredSelection) list 858 .getSelection()).toList(); 859 860 list.setItemCount(contentProvider.getElements(null).length); 861 list.refresh(); 862 863 if (list.getTable().getItemCount() > 0) { 864 if (refreshWithLastSelection && lastRefreshSelection != null 866 && lastRefreshSelection.size() > 0) { 867 list.setSelection(new StructuredSelection( 868 lastRefreshSelection)); 869 } else { 870 refreshWithLastSelection = true; 871 list.getTable().setSelection(0); 872 list.getTable().notifyListeners(SWT.Selection, new Event()); 873 } 874 } else { 875 list.setSelection(StructuredSelection.EMPTY); 876 } 877 878 } 879 880 scheduleProgressMessageRefresh(); 881 } 882 883 888 public void updateProgressLabel() { 889 scheduleProgressMessageRefresh(); 890 } 891 892 907 public void reloadCache(boolean checkDuplicates, IProgressMonitor monitor) { 908 if (list != null && !list.getTable().isDisposed() 909 && contentProvider != null) { 910 contentProvider.reloadCache(checkDuplicates, monitor); 911 } 912 } 913 914 917 public void scheduleRefresh() { 918 refreshCacheJob.cancelAll(); 919 refreshCacheJob.schedule(); 920 } 921 922 925 public void scheduleProgressMessageRefresh() { 926 if (filterJob.getState() != Job.RUNNING 927 && refreshProgressMessageJob.getState() != Job.RUNNING) 928 refreshProgressMessageJob.scheduleProgressRefresh(null); 929 } 930 931 936 protected void computeResult() { 937 938 List selectedElements = ((StructuredSelection) list.getSelection()) 939 .toList(); 940 941 List objectsToReturn = new ArrayList (); 942 943 Object item = null; 944 945 for (Iterator it = selectedElements.iterator(); it.hasNext();) { 946 item = it.next(); 947 948 if (!(item instanceof ItemsListSeparator)) { 949 accessedHistoryItem(item); 950 objectsToReturn.add(item); 951 } 952 } 953 954 setResult(objectsToReturn); 955 } 956 957 960 protected void updateStatus(IStatus status) { 961 this.status = status; 962 super.updateStatus(status); 963 } 964 965 968 protected void okPressed() { 969 if (status != null 970 && (status.isOK() || status.getCode() == IStatus.INFO)) { 971 super.okPressed(); 972 } 973 } 974 975 984 public void setInitialPattern(String text) { 985 setInitialPattern(text, FULL_SELECTION); 986 } 987 988 1000 public void setInitialPattern(String text, int selectionMode) { 1001 this.initialPatternText = text; 1002 this.selectionMode = selectionMode; 1003 } 1004 1005 1011 protected String getInitialPattern() { 1012 return this.initialPatternText; 1013 } 1014 1015 1020 protected StructuredSelection getSelectedItems() { 1021 1022 StructuredSelection selection = (StructuredSelection) list 1023 .getSelection(); 1024 1025 List selectedItems = selection.toList(); 1026 Object itemToRemove = null; 1027 1028 for (Iterator it = selection.iterator(); it.hasNext();) { 1029 Object item = it.next(); 1030 if (item instanceof ItemsListSeparator) { 1031 itemToRemove = item; 1032 break; 1033 } 1034 } 1035 1036 if (itemToRemove == null) 1037 return new StructuredSelection(selectedItems); 1038 List newItems = new ArrayList (selectedItems); 1040 newItems.remove(itemToRemove); 1041 return new StructuredSelection(newItems); 1042 1043 } 1044 1045 1054 protected abstract IStatus validateItem(Object item); 1055 1056 1063 protected abstract ItemsFilter createFilter(); 1064 1065 1070 protected void applyFilter() { 1071 1072 ItemsFilter newFilter = createFilter(); 1073 1074 if (filter != null && filter.equalsFilter(newFilter)) { 1077 return; 1078 } 1079 1080 filterHistoryJob.cancel(); 1081 filterJob.cancel(); 1082 1083 this.filter = newFilter; 1084 1085 if (this.filter != null) { 1086 filterHistoryJob.schedule(); 1087 } 1088 } 1089 1090 1098 protected abstract Comparator getItemsComparator(); 1099 1100 1114 protected abstract void fillContentProvider( 1115 AbstractContentProvider contentProvider, ItemsFilter itemsFilter, 1116 IProgressMonitor progressMonitor) throws CoreException; 1117 1118 1124 private void removeSelectedItems(List items) { 1125 for (Iterator iter = items.iterator(); iter.hasNext();) { 1126 Object item = iter.next(); 1127 removeHistoryItem(item); 1128 } 1129 refreshWithLastSelection = false; 1130 contentProvider.refresh(); 1131 } 1132 1133 1140 protected Object removeHistoryItem(Object item) { 1141 return contentProvider.removeHistoryElement(item); 1142 } 1143 1144 1150 protected void accessedHistoryItem(Object item) { 1151 contentProvider.addHistoryElement(item); 1152 } 1153 1154 1159 private Comparator getHistoryComparator() { 1160 return new HistoryComparator(); 1161 } 1162 1163 1169 protected SelectionHistory getSelectionHistory() { 1170 return this.contentProvider.getSelectionHistory(); 1171 } 1172 1173 1179 protected void setSelectionHistory(SelectionHistory selectionHistory) { 1180 if (this.contentProvider != null) 1181 this.contentProvider.setSelectionHistory(selectionHistory); 1182 } 1183 1184 1192 public boolean isHistoryElement(Object item) { 1193 return this.contentProvider.isHistoryElement(item); 1194 } 1195 1196 1204 public boolean isDuplicateElement(Object item) { 1205 return this.contentProvider.isDuplicateElement(item); 1206 } 1207 1208 1214 public void setSeparatorLabel(String separatorLabel) { 1215 this.itemsListSeparator = new ItemsListSeparator(separatorLabel); 1216 } 1217 1218 1229 public abstract String getElementName(Object item); 1230 1231 private class ToggleStatusLineAction extends Action { 1232 1233 1236 public ToggleStatusLineAction() { 1237 super( 1238 WorkbenchMessages.FilteredItemsSelectionDialog_toggleStatusAction, 1239 IAction.AS_CHECK_BOX); 1240 } 1241 1242 public void run() { 1243 details.setVisible(isChecked()); 1244 } 1245 } 1246 1247 1278 private class RefreshJob extends UIJob { 1279 1280 1283 public RefreshJob() { 1284 super(FilteredItemsSelectionDialog.this.getParentShell() 1285 .getDisplay(), 1286 WorkbenchMessages.FilteredItemsSelectionDialog_refreshJob); 1287 setSystem(true); 1288 } 1289 1290 1295 public IStatus runInUIThread(IProgressMonitor monitor) { 1296 if (monitor.isCanceled()) 1297 return new Status(IStatus.OK, WorkbenchPlugin.PI_WORKBENCH, 1298 IStatus.OK, EMPTY_STRING, null); 1299 1300 if (FilteredItemsSelectionDialog.this != null) { 1301 FilteredItemsSelectionDialog.this.refresh(); 1302 } 1303 1304 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, 1305 EMPTY_STRING, null); 1306 } 1307 1308 } 1309 1310 1316 private class RefreshProgressMessageJob extends UIJob { 1317 1318 private GranualProgressMonitor progressMonitor; 1319 1320 1323 public RefreshProgressMessageJob() { 1324 super( 1325 FilteredItemsSelectionDialog.this.getParentShell() 1326 .getDisplay(), 1327 WorkbenchMessages.FilteredItemsSelectionDialog_progressRefreshJob); 1328 setSystem(true); 1329 } 1330 1331 1336 public IStatus runInUIThread(IProgressMonitor monitor) { 1337 1338 if (!progressLabel.isDisposed()) 1339 progressLabel.setText(progressMonitor != null ? progressMonitor 1340 .getMessage() : EMPTY_STRING); 1341 1342 if (progressMonitor == null || progressMonitor.isDone()) { 1343 return new Status(IStatus.CANCEL, PlatformUI.PLUGIN_ID, 1344 IStatus.CANCEL, EMPTY_STRING, null); 1345 } 1346 1347 schedule(500); 1349 1350 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, 1351 EMPTY_STRING, null); 1352 } 1353 1354 1360 public void scheduleProgressRefresh( 1361 GranualProgressMonitor progressMonitor) { 1362 this.progressMonitor = progressMonitor; 1363 schedule(200); 1366 } 1367 1368 } 1369 1370 1377 private class RefreshCacheJob extends Job { 1378 1379 private RefreshJob refreshJob = new RefreshJob(); 1380 1381 1384 public RefreshCacheJob() { 1385 super( 1386 WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob); 1387 setSystem(true); 1388 } 1389 1390 1393 public void cancelAll() { 1394 cancel(); 1395 refreshJob.cancel(); 1396 } 1397 1398 1403 protected IStatus run(IProgressMonitor monitor) { 1404 if (monitor.isCanceled()) { 1405 return new Status(IStatus.CANCEL, WorkbenchPlugin.PI_WORKBENCH, 1406 IStatus.CANCEL, EMPTY_STRING, null); 1407 } 1408 1409 if (FilteredItemsSelectionDialog.this != null) { 1410 GranualProgressMonitor wrappedMonitor = new GranualProgressMonitor( 1411 monitor); 1412 FilteredItemsSelectionDialog.this.reloadCache(true, 1413 wrappedMonitor); 1414 } 1415 1416 if (!monitor.isCanceled()) { 1417 refreshJob.schedule(); 1418 } 1419 1420 return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, 1421 EMPTY_STRING, null); 1422 1423 } 1424 1425 1430 protected void canceling() { 1431 super.canceling(); 1432 contentProvider.stopReloadingCache(); 1433 } 1434 1435 } 1436 1437 private class RemoveHistoryItemAction extends Action { 1438 1439 1442 public RemoveHistoryItemAction() { 1443 super( 1444 WorkbenchMessages.FilteredItemsSelectionDialog_removeItemsFromHistoryAction); 1445 } 1446 1447 1452 public void run() { 1453 List selectedElements = ((StructuredSelection) list.getSelection()) 1454 .toList(); 1455 removeSelectedItems(selectedElements); 1456 } 1457 } 1458 1459 private class ItemsListLabelProvider extends LabelProvider implements 1460 IColorProvider, IFontProvider, ILabelProviderListener { 1461 private ILabelProvider provider; 1462 1463 private ILabelDecorator selectionDecorator; 1464 1465 private ListenerList listeners = new ListenerList(); 1467 1468 1476 public ItemsListLabelProvider(ILabelProvider provider, 1477 ILabelDecorator selectionDecorator) { 1478 Assert.isNotNull(provider); 1479 this.provider = provider; 1480 this.selectionDecorator = selectionDecorator; 1481 1482 provider.addListener(this); 1483 1484 if (selectionDecorator != null) { 1485 selectionDecorator.addListener(this); 1486 } 1487 } 1488 1489 1495 public void setSelectionDecorator(ILabelDecorator newSelectionDecorator) { 1496 if (selectionDecorator != null) { 1497 selectionDecorator.removeListener(this); 1498 selectionDecorator.dispose(); 1499 } 1500 1501 selectionDecorator = newSelectionDecorator; 1502 1503 if (selectionDecorator != null) { 1504 selectionDecorator.addListener(this); 1505 } 1506 } 1507 1508 1513 public ILabelDecorator getSelectionDecorator() { 1514 return selectionDecorator; 1515 } 1516 1517 1524 public void setProvider(ILabelProvider newProvider) { 1525 Assert.isNotNull(newProvider); 1526 provider.removeListener(this); 1527 provider.dispose(); 1528 1529 provider = newProvider; 1530 1531 if (provider != null) { 1532 provider.addListener(this); 1533 } 1534 } 1535 1536 1541 public ILabelProvider getProvider() { 1542 return provider; 1543 } 1544 1545 1550 public Image getImage(Object element) { 1551 if (element instanceof ItemsListSeparator) { 1552 return WorkbenchImages 1553 .getImage(IWorkbenchGraphicConstants.IMG_OBJ_SEPARATOR); 1554 } 1555 1556 return provider.getImage(element); 1557 } 1558 1559 1564 public String getText(Object element) { 1565 if (element instanceof ItemsListSeparator) { 1566 return getSeparatorLabel(((ItemsListSeparator) element) 1567 .getName()); 1568 } 1569 1570 String str = provider.getText(element); 1571 1572 if (selectionDecorator != null && element != null) { 1573 1574 1578 int[] selectionIndices = list.getTable().getSelectionIndices(); 1579 List elements = Arrays 1580 .asList(contentProvider.getElements(null)); 1581 for (int i = 0; i < selectionIndices.length; i++) { 1582 if (elements.size() > selectionIndices[i] 1583 && element 1584 .equals(elements.get(selectionIndices[i]))) { 1585 str = selectionDecorator.decorateText(str, element); 1586 break; 1587 } 1588 } 1589 } 1590 return str; 1591 } 1592 1593 private String getSeparatorLabel(String separatorLabel) { 1594 Rectangle rect = list.getTable().getBounds(); 1595 1596 int borderWidth = list.getTable().computeTrim(0, 0, 0, 0).width; 1597 1598 int imageWidth = WorkbenchImages.getImage( 1599 IWorkbenchGraphicConstants.IMG_OBJ_SEPARATOR).getBounds().width; 1600 1601 int width = rect.width - borderWidth - imageWidth; 1602 1603 GC gc = new GC(list.getTable()); 1604 gc.setFont(list.getTable().getFont()); 1605 1606 int fSeparatorWidth = gc.getAdvanceWidth('-'); 1607 int fMessageLength = gc.textExtent(separatorLabel).x; 1608 1609 gc.dispose(); 1610 1611 StringBuffer dashes = new StringBuffer (); 1612 int chars = (((width - fMessageLength) / fSeparatorWidth) / 2) - 2; 1613 for (int i = 0; i < chars; i++) { 1614 dashes.append('-'); 1615 } 1616 1617 StringBuffer result = new StringBuffer (); 1618 result.append(dashes); 1619 result.append(" " + separatorLabel + " "); result.append(dashes); 1621 return result.toString().trim(); 1622 } 1623 1624 1629 public void addListener(ILabelProviderListener listener) { 1630 listeners.add(listener); 1631 } 1632 1633 1638 public void dispose() { 1639 provider.removeListener(this); 1640 provider.dispose(); 1641 1642 if (selectionDecorator != null) { 1643 selectionDecorator.removeListener(this); 1644 selectionDecorator.dispose(); 1645 } 1646 1647 super.dispose(); 1648 } 1649 1650 1656 public boolean isLabelProperty(Object element, String property) { 1657 if (provider.isLabelProperty(element, property)) { 1658 return true; 1659 } 1660 if (selectionDecorator != null 1661 && selectionDecorator.isLabelProperty(element, property)) { 1662 return true; 1663 } 1664 return false; 1665 } 1666 1667 1672 public void removeListener(ILabelProviderListener listener) { 1673 listeners.remove(listener); 1674 } 1675 1676 1681 public Color getBackground(Object element) { 1682 if (element instanceof ItemsListSeparator) { 1683 return null; 1684 } 1685 if (provider instanceof IColorProvider) { 1686 return ((IColorProvider) provider).getBackground(element); 1687 } 1688 return null; 1689 } 1690 1691 1696 public Color getForeground(Object element) { 1697 if (element instanceof ItemsListSeparator) { 1698 return Display.getCurrent().getSystemColor( 1699 SWT.COLOR_WIDGET_NORMAL_SHADOW); 1700 } 1701 if (provider instanceof IColorProvider) { 1702 return ((IColorProvider) provider).getForeground(element); 1703 } 1704 return null; 1705 } 1706 1707 1712 public Font getFont(Object element) { 1713 if (element instanceof ItemsListSeparator) { 1714 return null; 1715 } 1716 if (provider instanceof IFontProvider) { 1717 return ((IFontProvider) provider).getFont(element); 1718 } 1719 return null; 1720 } 1721 1722 1727 public void labelProviderChanged(LabelProviderChangedEvent event) { 1728 Object [] l = listeners.getListeners(); 1729 for (int i = 0; i < listeners.size(); i++) { 1730 ((ILabelProviderListener) l[i]).labelProviderChanged(event); 1731 } 1732 } 1733 } 1734 1735 1739 private class ItemsListSeparator { 1740 1741 private String name; 1742 1743 1749 public ItemsListSeparator(String name) { 1750 this.name = name; 1751 } 1752 1753 1758 public String getName() { 1759 return name; 1760 } 1761 } 1762 1763 1771 private class GranualProgressMonitor extends ProgressMonitorWrapper { 1772 1773 private String name; 1774 1775 private String subName; 1776 1777 private int totalWork; 1778 1779 private double worked; 1780 1781 private boolean done; 1782 1783 1789 public GranualProgressMonitor(IProgressMonitor monitor) { 1790 super(monitor); 1791 } 1792 1793 1798 public boolean isDone() { 1799 return done; 1800 } 1801 1802 1807 public void setTaskName(String name) { 1808 super.setTaskName(name); 1809 this.name = name; 1810 this.subName = null; 1811 } 1812 1813 1818 public void subTask(String name) { 1819 super.subTask(name); 1820 this.subName = name; 1821 } 1822 1823 1829 public void beginTask(String name, int totalWork) { 1830 super.beginTask(name, totalWork); 1831 if (this.name == null) 1832 this.name = name; 1833 this.totalWork = totalWork; 1834 refreshProgressMessageJob.scheduleProgressRefresh(this); 1835 } 1836 1837 1842 public void worked(int work) { 1843 super.worked(work); 1844 internalWorked(work); 1845 } 1846 1847 1852 public void done() { 1853 done = true; 1854 super.done(); 1855 } 1856 1857 1862 public void setCanceled(boolean b) { 1863 done = b; 1864 super.setCanceled(b); 1865 } 1866 1867 1872 public void internalWorked(double work) { 1873 worked = worked + work; 1874 } 1875 1876 private String getMessage() { 1877 if (done) 1878 return ""; 1880 String message; 1881 1882 if (name == null) { 1883 message = subName == null ? "" : subName; } else { 1885 message = subName == null ? name 1886 : NLS 1887 .bind( 1888 WorkbenchMessages.FilteredItemsSelectionDialog_subtaskProgressMessage, 1889 new Object [] { name, subName }); 1890 } 1891 if (totalWork == 0) 1892 return message; 1893 1894 return NLS 1895 .bind( 1896 WorkbenchMessages.FilteredItemsSelectionDialog_taskProgressMessage, 1897 new Object [] { 1898 message, 1899 new Integer ( 1900 (int) ((worked * 100) / totalWork)) }); 1901 1902 } 1903 1904 } 1905 1906 1909 private class FilterHistoryJob extends Job { 1910 1911 1914 private ItemsFilter itemsFilter; 1915 1916 1919 public FilterHistoryJob() { 1920 super(WorkbenchMessages.FilteredItemsSelectionDialog_jobLabel); 1921 setSystem(true); 1922 } 1923 1924 1929 protected IStatus run(IProgressMonitor monitor) { 1930 1931 this.itemsFilter = filter; 1932 1933 contentProvider.reset(); 1934 1935 refreshWithLastSelection = false; 1936 1937 contentProvider.addHistoryItems(itemsFilter); 1938 1939 if (!(lastCompletedFilter != null && lastCompletedFilter 1940 .isSubFilter(this.itemsFilter))) 1941 contentProvider.refresh(); 1942 1943 filterJob.schedule(); 1944 1945 return Status.OK_STATUS; 1946 } 1947 1948 } 1949 1950 1962 private class FilterJob extends Job { 1963 1964 1967 protected ItemsFilter itemsFilter; 1968 1969 1972 public FilterJob() { 1973 super(WorkbenchMessages.FilteredItemsSelectionDialog_jobLabel); 1974 setSystem(true); 1975 } 1976 1977 1982 protected final IStatus run(IProgressMonitor parent) { 1983 GranualProgressMonitor monitor = new GranualProgressMonitor(parent); 1984 return doRun(monitor); 1985 } 1986 1987 1995 protected IStatus doRun(GranualProgressMonitor monitor) { 1996 try { 1997 internalRun(monitor); 1998 } catch (CoreException e) { 1999 cancel(); 2000 return new Status( 2001 IStatus.ERROR, 2002 PlatformUI.PLUGIN_ID, 2003 IStatus.ERROR, 2004 WorkbenchMessages.FilteredItemsSelectionDialog_jobError, 2005 e); 2006 } 2007 return Status.OK_STATUS; 2008 } 2009 2010 2016 private void internalRun(GranualProgressMonitor monitor) 2017 throws CoreException { 2018 try { 2019 if (monitor.isCanceled()) 2020 return; 2021 2022 this.itemsFilter = filter; 2023 2024 if (filter.getPattern().length() != 0) { 2025 filterContent(monitor); 2026 } 2027 2028 if (monitor.isCanceled()) 2029 return; 2030 2031 contentProvider.refresh(); 2032 } finally { 2033 monitor.done(); 2034 } 2035 } 2036 2037 2044 protected void filterContent(GranualProgressMonitor monitor) 2045 throws CoreException { 2046 2047 if (lastCompletedFilter != null 2048 && lastCompletedFilter.isSubFilter(this.itemsFilter)) { 2049 2050 int length = lastCompletedResult.size() / 500; 2051 monitor 2052 .beginTask( 2053 WorkbenchMessages.FilteredItemsSelectionDialog_cacheSearchJob_taskName, 2054 length); 2055 2056 for (int pos = 0; pos < lastCompletedResult.size(); pos++) { 2057 2058 Object item = lastCompletedResult.get(pos); 2059 if (monitor.isCanceled()) 2060 break; 2061 contentProvider.add(item, itemsFilter); 2062 2063 if ((pos % 500) == 0) { 2064 monitor.worked(1); 2065 } 2066 } 2067 2068 } else { 2069 2070 lastCompletedFilter = null; 2071 lastCompletedResult = null; 2072 2073 SubProgressMonitor subMonitor = null; 2074 if (monitor != null) { 2075 monitor 2076 .beginTask( 2077 WorkbenchMessages.FilteredItemsSelectionDialog_searchJob_taskName, 2078 100); 2079 subMonitor = new SubProgressMonitor(monitor, 95); 2080 2081 } 2082 2083 fillContentProvider(contentProvider, itemsFilter, subMonitor); 2084 2085 if (monitor != null && !monitor.isCanceled()) { 2086 monitor.worked(2); 2087 contentProvider.rememberResult(itemsFilter); 2088 monitor.worked(3); 2089 } 2090 } 2091 2092 } 2093 2094 } 2095 2096 2104 protected static abstract class SelectionHistory { 2105 2106 private static final String DEFAULT_ROOT_NODE_NAME = "historyRootNode"; 2108 private static final String DEFAULT_INFO_NODE_NAME = "infoNode"; 2110 private static final int MAX_HISTORY_SIZE = 60; 2111 2112 private final List historyList; 2113 2114 private final String rootNodeName; 2115 2116 private final String infoNodeName; 2117 2118 private SelectionHistory(String rootNodeName, String infoNodeName) { 2119 2120 historyList = Collections.synchronizedList(new LinkedList () { 2121 2122 private static final long serialVersionUID = 0L; 2123 2124 2129 public boolean add(Object arg0) { 2130 if (this.size() > MAX_HISTORY_SIZE) 2131 this.removeFirst(); 2132 if (!this.contains(arg0)) 2133 return super.add(arg0); 2134 return false; 2135 } 2136 2137 }); 2138 2139 this.rootNodeName = rootNodeName; 2140 this.infoNodeName = infoNodeName; 2141 } 2142 2143 2146 public SelectionHistory() { 2147 this(DEFAULT_ROOT_NODE_NAME, DEFAULT_INFO_NODE_NAME); 2148 } 2149 2150 2156 public synchronized void accessed(Object object) { 2157 historyList.add(object); 2158 } 2159 2160 2168 public synchronized boolean contains(Object object) { 2169 return historyList.contains(object); 2170 } 2171 2172 2177 public synchronized boolean isEmpty() { 2178 return historyList.isEmpty(); 2179 } 2180 2181 2189 public synchronized boolean remove(Object element) { 2190 return historyList.remove(element); 2191 } 2192 2193 2199 public void load(IMemento memento) { 2200 2201 XMLMemento historyMemento = (XMLMemento) memento 2202 .getChild(rootNodeName); 2203 2204 if (historyMemento == null) { 2205 return; 2206 } 2207 2208 IMemento[] mementoElements = historyMemento 2209 .getChildren(infoNodeName); 2210 for (int i = 0; i < mementoElements.length; ++i) { 2211 IMemento mementoElement = mementoElements[i]; 2212 Object object = restoreItemFromMemento(mementoElement); 2213 if (object != null) { 2214 historyList.add(object); 2215 } 2216 } 2217 } 2218 2219 2225 public void save(IMemento memento) { 2226 2227 IMemento historyMemento = memento.createChild(rootNodeName); 2228 2229 Object [] items = getHistoryItems(); 2230 for (int i = 0; i < items.length; i++) { 2231 Object item = items[i]; 2232 IMemento elementMemento = historyMemento 2233 .createChild(infoNodeName); 2234 storeItemToMemento(item, elementMemento); 2235 } 2236 2237 } 2238 2239 2244 public synchronized Object [] getHistoryItems() { 2245 return historyList.toArray(); 2246 } 2247 2248 2256 protected abstract Object restoreItemFromMemento(IMemento memento); 2257 2258 2266 protected abstract void storeItemToMemento(Object item, IMemento memento); 2267 2268 } 2269 2270 2274 protected abstract class ItemsFilter { 2275 2276 protected SearchPattern patternMatcher; 2277 2278 2281 public ItemsFilter() { 2282 this(new SearchPattern()); 2283 } 2284 2285 2291 public ItemsFilter(SearchPattern searchPattern) { 2292 patternMatcher = searchPattern; 2293 String stringPattern = ""; if (pattern != null && !pattern.getText().equals("*")) { stringPattern = pattern.getText(); 2296 } 2297 patternMatcher.setPattern(stringPattern); 2298 } 2299 2300 2314 public boolean isSubFilter(ItemsFilter filter) { 2315 if (filter != null) { 2316 return this.patternMatcher.isSubPattern(filter.patternMatcher); 2317 } 2318 return false; 2319 } 2320 2321 2334 public boolean equalsFilter(ItemsFilter filter) { 2335 if (filter != null 2336 && filter.patternMatcher.equalsPattern(this.patternMatcher)) { 2337 return true; 2338 } 2339 return false; 2340 } 2341 2342 2348 public boolean isCamelCasePattern() { 2349 return patternMatcher.getMatchRule() == SearchPattern.RULE_CAMELCASE_MATCH; 2350 } 2351 2352 2359 public String getPattern() { 2360 return patternMatcher.getPattern(); 2361 } 2362 2363 2370 public int getMatchRule() { 2371 return patternMatcher.getMatchRule(); 2372 } 2373 2374 2381 protected boolean matches(String text) { 2382 return patternMatcher.matches(text); 2383 } 2384 2385 2395 public boolean matchesRawNamePattern(Object item) { 2396 String prefix = patternMatcher.getPattern(); 2397 String text = getElementName(item); 2398 2399 if (text == null) 2400 return false; 2401 2402 int textLength = text.length(); 2403 int prefixLength = prefix.length(); 2404 if (textLength < prefixLength) { 2405 return false; 2406 } 2407 for (int i = prefixLength - 1; i >= 0; i--) { 2408 if (Character.toLowerCase(prefix.charAt(i)) != Character 2409 .toLowerCase(text.charAt(i))) 2410 return false; 2411 } 2412 return true; 2413 } 2414 2415 2422 public abstract boolean matchItem(Object item); 2423 2424 2432 public abstract boolean isConsistentItem(Object item); 2433 2434 } 2435 2436 2440 protected abstract class AbstractContentProvider { 2441 2452 public abstract void add(Object item, ItemsFilter itemsFilter); 2453 } 2454 2455 2471 private class ContentProvider extends AbstractContentProvider implements 2472 IStructuredContentProvider, ILazyContentProvider { 2473 2474 private SelectionHistory selectionHistory; 2475 2476 2482 private Set items; 2483 2484 2487 private Set duplicates; 2488 2489 2492 private List filters; 2493 2494 2500 private List lastFilteredItems; 2501 2502 2508 private List lastSortedItems; 2509 2510 2519 private boolean reset; 2520 2521 2526 public ContentProvider(SelectionHistory selectionHistory) { 2527 this(); 2528 this.selectionHistory = selectionHistory; 2529 } 2530 2531 2534 public ContentProvider() { 2535 this.items = Collections.synchronizedSet(new HashSet (2048)); 2536 this.duplicates = Collections.synchronizedSet(new HashSet (256)); 2537 this.lastFilteredItems = new ArrayList (); 2538 this.lastSortedItems = Collections.synchronizedList(new ArrayList ( 2539 2048)); 2540 } 2541 2542 2548 public void setSelectionHistory(SelectionHistory selectionHistory) { 2549 this.selectionHistory = selectionHistory; 2550 } 2551 2552 2555 public SelectionHistory getSelectionHistory() { 2556 return selectionHistory; 2557 } 2558 2559 2562 public void reset() { 2563 reset = true; 2564 this.items.clear(); 2565 this.duplicates.clear(); 2566 this.lastSortedItems.clear(); 2567 } 2568 2569 2572 public void stopReloadingCache() { 2573 reset = true; 2574 } 2575 2576 2582 public void add(Object item, ItemsFilter itemsFilter) { 2583 if (itemsFilter == filter) { 2584 if (itemsFilter != null) { 2585 if (itemsFilter.matchItem(item)) { 2586 this.items.add(item); 2587 } 2588 } else { 2589 this.items.add(item); 2590 } 2591 } 2592 } 2593 2594 2599 public void addHistoryItems(ItemsFilter itemsFilter) { 2600 if (this.selectionHistory != null) { 2601 Object [] items = this.selectionHistory.getHistoryItems(); 2602 for (int i = 0; i < items.length; i++) { 2603 Object item = items[i]; 2604 if (itemsFilter == filter) { 2605 if (itemsFilter != null) { 2606 if (itemsFilter.matchItem(item)) { 2607 if (itemsFilter.isConsistentItem(item)) { 2608 this.items.add(item); 2609 } else { 2610 this.selectionHistory.remove(item); 2611 } 2612 } 2613 } 2614 } 2615 } 2616 } 2617 } 2618 2619 2622 public void refresh() { 2623 scheduleRefresh(); 2624 } 2625 2626 2634 public Object removeHistoryElement(Object item) { 2635 if (this.selectionHistory != null) 2636 this.selectionHistory.remove(item); 2637 if (filter == null || filter.getPattern().length() == 0) { 2638 items.remove(item); 2639 duplicates.remove(item); 2640 this.lastSortedItems.remove(item); 2641 } 2642 2643 synchronized (lastSortedItems) { 2644 Collections.sort(lastSortedItems, getHistoryComparator()); 2645 } 2646 return item; 2647 } 2648 2649 2655 public void addHistoryElement(Object item) { 2656 if (this.selectionHistory != null) 2657 this.selectionHistory.accessed(item); 2658 if (filter == null || !filter.matchItem(item)) { 2659 this.items.remove(item); 2660 this.duplicates.remove(item); 2661 this.lastSortedItems.remove(item); 2662 } 2663 synchronized (lastSortedItems) { 2664 Collections.sort(lastSortedItems, getHistoryComparator()); 2665 } 2666 this.refresh(); 2667 } 2668 2669 2673 public boolean isHistoryElement(Object item) { 2674 if (this.selectionHistory != null) { 2675 return this.selectionHistory.contains(item); 2676 } 2677 return false; 2678 } 2679 2680 2689 public void setDuplicateElement(Object item, boolean isDuplicate) { 2690 if (this.items.contains(item)) { 2691 if (isDuplicate) 2692 this.duplicates.add(item); 2693 else 2694 this.duplicates.remove(item); 2695 } 2696 } 2697 2698 2705 public boolean isDuplicateElement(Object item) { 2706 return duplicates.contains(item); 2707 } 2708 2709 2715 public void loadHistory(IMemento memento) { 2716 if (this.selectionHistory != null) 2717 this.selectionHistory.load(memento); 2718 } 2719 2720 2726 public void saveHistory(IMemento memento) { 2727 if (this.selectionHistory != null) 2728 this.selectionHistory.save(memento); 2729 } 2730 2731 2736 private Object [] getSortedItems() { 2737 if (lastSortedItems.size() != items.size()) { 2738 synchronized (lastSortedItems) { 2739 lastSortedItems.clear(); 2740 lastSortedItems.addAll(items); 2741 Collections.sort(lastSortedItems, getHistoryComparator()); 2742 } 2743 } 2744 return lastSortedItems.toArray(); 2745 } 2746 2747 2752 public void rememberResult(ItemsFilter itemsFilter) { 2753 List itemsList = Collections.synchronizedList(Arrays 2754 .asList(getSortedItems())); 2755 if (itemsFilter == filter) { 2757 lastCompletedFilter = itemsFilter; 2758 lastCompletedResult = itemsList; 2759 } 2760 2761 } 2762 2763 2768 public Object [] getElements(Object inputElement) { 2769 return lastFilteredItems.toArray(); 2770 } 2771 2772 2777 public void dispose() { 2778 } 2779 2780 2786 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 2787 } 2788 2789 2794 public void updateElement(int index) { 2795 2796 FilteredItemsSelectionDialog.this.list.replace((lastFilteredItems 2797 .size() > index) ? lastFilteredItems.get(index) : null, 2798 index); 2799 2800 } 2801 2802 2815 public void reloadCache(boolean checkDuplicates, 2816 IProgressMonitor monitor) { 2817 2818 reset = false; 2819 2820 if (monitor != null) { 2821 int totalWork = checkDuplicates ? 200 : 100; 2823 2824 monitor 2825 .beginTask( 2826 WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob, 2827 totalWork); 2828 } 2829 2830 2832 lastFilteredItems = Arrays.asList(getFilteredItems(list.getInput(), 2833 monitor != null ? new SubProgressMonitor(monitor, 100) 2834 : null)); 2835 2836 if (reset || (monitor != null && monitor.isCanceled())) { 2837 if (monitor != null) 2838 monitor.done(); 2839 return; 2840 } 2841 2842 if (checkDuplicates) { 2843 checkDuplicates(monitor); 2844 } 2845 if (monitor != null) 2846 monitor.done(); 2847 } 2848 2849 private void checkDuplicates(IProgressMonitor monitor) { 2850 synchronized (lastFilteredItems) { 2851 IProgressMonitor subMonitor = null; 2852 int reportEvery = lastFilteredItems.size() / 20; 2853 if (monitor != null) { 2854 subMonitor = new SubProgressMonitor(monitor, 100); 2855 subMonitor 2856 .beginTask( 2857 WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob_checkDuplicates, 2858 5); 2859 } 2860 HashMap helperMap = new HashMap (); 2861 for (int i = 0; i < lastFilteredItems.size(); i++) { 2862 if (reset 2863 || (subMonitor != null && subMonitor.isCanceled())) 2864 return; 2865 Object item = lastFilteredItems.get(i); 2866 2867 if (!(item instanceof ItemsListSeparator)) { 2868 Object previousItem = helperMap.put( 2869 getElementName(item), item); 2870 if (previousItem != null) { 2871 setDuplicateElement(previousItem, true); 2872 setDuplicateElement(item, true); 2873 } else { 2874 setDuplicateElement(item, false); 2875 } 2876 } 2877 2878 if (subMonitor != null && reportEvery != 0 2879 && (i + 1) % reportEvery == 0) 2880 subMonitor.worked(1); 2881 } 2882 helperMap.clear(); 2883 } 2884 } 2885 2886 2896 protected Object [] getFilteredItems(Object parent, 2897 IProgressMonitor monitor) { 2898 int ticks = 100; 2899 2900 if (monitor != null) { 2901 monitor 2902 .beginTask( 2903 WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob_getFilteredElements, 2904 ticks); 2905 if (filters != null) { 2906 ticks /= (filters.size() + 2); 2907 } else { 2908 ticks /= 2; 2909 } 2910 } 2911 2912 Object [] filteredElements = getSortedItems(); 2914 2915 if (monitor != null) { 2916 monitor.worked(ticks); 2917 } 2918 2919 if (filters != null && filteredElements != null) { 2921 for (Iterator iter = filters.iterator(); iter.hasNext();) { 2922 ViewerFilter f = (ViewerFilter) iter.next(); 2923 filteredElements = f.filter(list, parent, filteredElements); 2924 if (monitor != null) 2925 monitor.worked(ticks); 2926 } 2927 } 2928 2929 if (filteredElements == null || monitor.isCanceled()) { 2930 if (monitor != null) 2931 monitor.done(); 2932 return new Object [0]; 2933 } 2934 2935 ArrayList preparedElements = new ArrayList (); 2936 boolean hasHistory = false; 2937 2938 if (filteredElements.length > 0) { 2939 if (isHistoryElement(filteredElements[0])) { 2940 hasHistory = true; 2941 } 2942 } 2943 2944 int reportEvery = filteredElements.length / ticks; 2945 2946 for (int i = 0; i < filteredElements.length; i++) { 2948 Object item = filteredElements[i]; 2949 2950 if (hasHistory && !isHistoryElement(item)) { 2951 preparedElements.add(itemsListSeparator); 2952 hasHistory = false; 2953 } 2954 2955 preparedElements.add(item); 2956 2957 if (monitor != null && reportEvery != 0 2958 && ((i + 1) % reportEvery == 0)) 2959 monitor.worked(1); 2960 } 2961 2962 if (monitor != null) 2963 monitor.done(); 2964 2965 return preparedElements.toArray(); 2966 } 2967 2968 2977 public void addFilter(ViewerFilter filter) { 2978 if (filters == null) { 2979 filters = new ArrayList (); 2980 } 2981 filters.add(filter); 2982 } 2986 2987 } 2988 2989 2992 private class NullContentProvider implements IContentProvider { 2993 2994 2999 public void dispose() { 3000 } 3001 3002 3008 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 3009 } 3010 3011 } 3012 3013 3018 private class DetailsContentViewer extends ContentViewer { 3019 3020 private CLabel label; 3021 3022 3027 private ViewForm viewForm; 3028 3029 3038 public DetailsContentViewer(Composite parent, int style) { 3039 viewForm = new ViewForm(parent, style); 3040 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 3041 gd.horizontalSpan = 2; 3042 viewForm.setLayoutData(gd); 3043 label = new CLabel(viewForm, SWT.FLAT); 3044 label.setFont(parent.getFont()); 3045 viewForm.setContent(label); 3046 hookControl(label); 3047 } 3048 3049 3055 public void setVisible(boolean visible) { 3056 GridData gd = (GridData) viewForm.getLayoutData(); 3057 gd.exclude = !visible; 3058 viewForm.getParent().layout(); 3059 } 3060 3061 3067 protected void inputChanged(Object input, Object oldInput) { 3068 if (oldInput == null) { 3069 if (input == null) { 3070 return; 3071 } 3072 refresh(); 3073 return; 3074 } 3075 3076 refresh(); 3077 3078 } 3079 3080 3085 protected void handleLabelProviderChanged( 3086 LabelProviderChangedEvent event) { 3087 if (event != null) { 3088 refresh(event.getElements()); 3089 } 3090 } 3091 3092 3097 public Control getControl() { 3098 return label; 3099 } 3100 3101 3106 public ISelection getSelection() { 3107 return null; 3109 } 3110 3111 3116 public void refresh() { 3117 Object input = this.getInput(); 3118 if (input != null) { 3119 ILabelProvider labelProvider = (ILabelProvider) getLabelProvider(); 3120 doRefresh(labelProvider.getText(input), labelProvider 3121 .getImage(input)); 3122 } else { 3123 doRefresh(null, null); 3124 } 3125 } 3126 3127 3135 private void doRefresh(String text, Image image) { 3136 label.setText(text); 3137 label.setImage(image); 3138 } 3139 3140 3146 public void setSelection(ISelection selection, boolean reveal) { 3147 } 3149 3150 3156 private void refresh(Object [] objs) { 3157 if (objs == null || getInput() == null) { 3158 return; 3159 } 3160 Object input = getInput(); 3161 for (int i = 0; i < objs.length; i++) { 3162 if (objs[i].equals(input)) { 3163 refresh(); 3164 break; 3165 } 3166 } 3167 } 3168 } 3169 3170 3173 private class CamelCaseComparator implements Comparator { 3174 3175 3180 public int compare(Object o1, Object o2) { 3181 3182 int leftCategory = getCamelCaseCategory(o1); 3183 int rightCategory = getCamelCaseCategory(o2); 3184 if (leftCategory < rightCategory) 3185 return -1; 3186 if (leftCategory > rightCategory) 3187 return +1; 3188 3189 return getItemsComparator().compare(o1, o2); 3190 } 3191 3192 private int getCamelCaseCategory(Object item) { 3193 if (filter == null) 3194 return 0; 3195 if (!filter.isCamelCasePattern()) 3196 return 0; 3197 return filter.matchesRawNamePattern(item) ? 0 : 1; 3198 } 3199 } 3200 3201 3204 private class HistoryComparator implements Comparator { 3205 3206 private CamelCaseComparator camelCaseComparator; 3207 3208 3211 public HistoryComparator() { 3212 this.camelCaseComparator = new CamelCaseComparator(); 3213 } 3214 3215 3220 public int compare(Object o1, Object o2) { 3221 if ((isHistoryElement(o1) && isHistoryElement(o2)) 3222 || (!isHistoryElement(o1) && !isHistoryElement(o2))) 3223 return this.camelCaseComparator.compare(o1, o2); 3224 3225 if (isHistoryElement(o1)) 3226 return -2; 3227 if (isHistoryElement(o2)) 3228 return +2; 3229 3230 return 0; 3231 } 3232 3233 } 3234 3235 3244 public Control getPatternControl() { 3245 return pattern; 3246 } 3247 3248} 3249 | Popular Tags |