1 11 package org.eclipse.search.ui.text; 12 13 import java.util.ArrayList ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.Set ; 17 18 import org.eclipse.core.runtime.Assert; 19 import org.eclipse.core.runtime.IProgressMonitor; 20 import org.eclipse.core.runtime.ISafeRunnable; 21 import org.eclipse.core.runtime.IStatus; 22 import org.eclipse.core.runtime.SafeRunner; 23 import org.eclipse.core.runtime.Status; 24 25 import org.eclipse.swt.SWT; 26 import org.eclipse.swt.layout.FillLayout; 27 import org.eclipse.swt.layout.GridData; 28 import org.eclipse.swt.widgets.Composite; 29 import org.eclipse.swt.widgets.Control; 30 import org.eclipse.swt.widgets.Display; 31 import org.eclipse.swt.widgets.Menu; 32 import org.eclipse.swt.widgets.Table; 33 import org.eclipse.swt.widgets.TableItem; 34 35 import org.eclipse.jface.action.Action; 36 import org.eclipse.jface.action.IAction; 37 import org.eclipse.jface.action.IMenuListener; 38 import org.eclipse.jface.action.IMenuManager; 39 import org.eclipse.jface.action.IToolBarManager; 40 import org.eclipse.jface.action.MenuManager; 41 import org.eclipse.jface.dialogs.ErrorDialog; 42 import org.eclipse.jface.dialogs.IDialogSettings; 43 import org.eclipse.jface.util.OpenStrategy; 44 import org.eclipse.jface.viewers.DecoratingLabelProvider; 45 import org.eclipse.jface.viewers.IBaseLabelProvider; 46 import org.eclipse.jface.viewers.IOpenListener; 47 import org.eclipse.jface.viewers.ISelection; 48 import org.eclipse.jface.viewers.ISelectionChangedListener; 49 import org.eclipse.jface.viewers.ISelectionProvider; 50 import org.eclipse.jface.viewers.IStructuredSelection; 51 import org.eclipse.jface.viewers.ITreeContentProvider; 52 import org.eclipse.jface.viewers.OpenEvent; 53 import org.eclipse.jface.viewers.SelectionChangedEvent; 54 import org.eclipse.jface.viewers.StructuredViewer; 55 import org.eclipse.jface.viewers.TableViewer; 56 import org.eclipse.jface.viewers.TreeViewer; 57 import org.eclipse.jface.viewers.Viewer; 58 59 import org.eclipse.jface.text.IRegion; 60 import org.eclipse.jface.text.Position; 61 import org.eclipse.jface.text.Region; 62 63 import org.eclipse.ui.IActionBars; 64 import org.eclipse.ui.IMemento; 65 import org.eclipse.ui.IWorkbenchWindow; 66 import org.eclipse.ui.PartInitException; 67 import org.eclipse.ui.PlatformUI; 68 import org.eclipse.ui.actions.ActionFactory; 69 import org.eclipse.ui.part.IPageSite; 70 import org.eclipse.ui.part.Page; 71 import org.eclipse.ui.part.PageBook; 72 import org.eclipse.ui.progress.UIJob; 73 import org.eclipse.ui.texteditor.IUpdate; 74 import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; 75 76 import org.eclipse.search.ui.IContextMenuConstants; 77 import org.eclipse.search.ui.IQueryListener; 78 import org.eclipse.search.ui.ISearchQuery; 79 import org.eclipse.search.ui.ISearchResult; 80 import org.eclipse.search.ui.ISearchResultListener; 81 import org.eclipse.search.ui.ISearchResultPage; 82 import org.eclipse.search.ui.ISearchResultViewPart; 83 import org.eclipse.search.ui.NewSearchUI; 84 import org.eclipse.search.ui.SearchResultEvent; 85 86 import org.eclipse.search.internal.ui.CopyToClipboardAction; 87 import org.eclipse.search.internal.ui.SearchPlugin; 88 import org.eclipse.search.internal.ui.SearchPluginImages; 89 import org.eclipse.search.internal.ui.SelectAllAction; 90 91 import org.eclipse.search2.internal.ui.MatchFilterSelectionAction; 92 import org.eclipse.search2.internal.ui.InternalSearchUI; 93 import org.eclipse.search2.internal.ui.MatchFilterAction; 94 import org.eclipse.search2.internal.ui.SearchMessages; 95 import org.eclipse.search2.internal.ui.SearchView; 96 import org.eclipse.search2.internal.ui.basic.views.CollapseAllAction; 97 import org.eclipse.search2.internal.ui.basic.views.ExpandAllAction; 98 import org.eclipse.search2.internal.ui.basic.views.INavigate; 99 import org.eclipse.search2.internal.ui.basic.views.RemoveAllMatchesAction; 100 import org.eclipse.search2.internal.ui.basic.views.RemoveMatchAction; 101 import org.eclipse.search2.internal.ui.basic.views.RemoveSelectedMatchesAction; 102 import org.eclipse.search2.internal.ui.basic.views.SetLayoutAction; 103 import org.eclipse.search2.internal.ui.basic.views.ShowNextResultAction; 104 import org.eclipse.search2.internal.ui.basic.views.ShowPreviousResultAction; 105 import org.eclipse.search2.internal.ui.basic.views.TableViewerNavigator; 106 import org.eclipse.search2.internal.ui.basic.views.TreeViewerNavigator; 107 import org.eclipse.search2.internal.ui.text.AnnotationManagers; 108 import org.eclipse.search2.internal.ui.text.PositionTracker; 109 110 125 public abstract class AbstractTextSearchViewPage extends Page implements ISearchResultPage { 126 private class UpdateUIJob extends UIJob { 127 128 public UpdateUIJob() { 129 super(SearchMessages.AbstractTextSearchViewPage_update_job_name); 130 setSystem(true); 131 } 132 133 public IStatus runInUIThread(IProgressMonitor monitor) { 134 Control control= getControl(); 135 if (control == null || control.isDisposed()) { 136 return Status.OK_STATUS; 138 } 139 runBatchedClear(); 140 runBatchedUpdates(); 141 if (hasMoreUpdates() || isQueryRunning()) { 142 schedule(500); 143 } else { 144 fIsUIUpdateScheduled= false; 145 turnOnDecoration(); 146 updateBusyLabel(); 147 if (fScheduleEnsureSelection) { 148 fScheduleEnsureSelection= false; 149 AbstractTextSearchResult result = getInput(); 150 if (result != null && fViewer.getSelection().isEmpty()) { 151 navigateNext(true); 152 } 153 } 154 } 155 fViewPart.updateLabel(); 156 return Status.OK_STATUS; 157 } 158 159 162 public boolean belongsTo(Object family) { 163 return family == AbstractTextSearchViewPage.this; 164 } 165 166 } 167 168 private class SelectionProviderAdapter implements ISelectionProvider, ISelectionChangedListener { 169 private ArrayList fListeners= new ArrayList (5); 170 171 public void addSelectionChangedListener(ISelectionChangedListener listener) { 172 fListeners.add(listener); 173 } 174 175 public ISelection getSelection() { 176 return fViewer.getSelection(); 177 } 178 179 public void removeSelectionChangedListener(ISelectionChangedListener listener) { 180 fListeners.remove(listener); 181 } 182 183 public void setSelection(ISelection selection) { 184 fViewer.setSelection(selection); 185 } 186 187 public void selectionChanged(SelectionChangedEvent event) { 188 SelectionChangedEvent wrappedEvent= new SelectionChangedEvent(this, event.getSelection()); 190 for (Iterator listeners= fListeners.iterator(); listeners.hasNext();) { 191 ISelectionChangedListener listener= (ISelectionChangedListener) listeners.next(); 192 listener.selectionChanged(wrappedEvent); 193 } 194 } 195 196 } 197 198 private volatile boolean fIsUIUpdateScheduled= false; 199 private volatile boolean fScheduleEnsureSelection= false; 200 private static final String KEY_LAYOUT = "org.eclipse.search.resultpage.layout"; 202 205 protected static final Match[] EMPTY_MATCH_ARRAY= new Match[0]; 206 207 private StructuredViewer fViewer; 208 private Composite fViewerContainer; 209 private Control fBusyLabel; 210 private PageBook fPagebook; 211 private boolean fIsBusyShown; 212 private ISearchResultViewPart fViewPart; 213 private Set fBatchedUpdates; 214 private boolean fBatchedClearAll; 215 216 private ISearchResultListener fListener; 217 private IQueryListener fQueryListener; 218 private MenuManager fMenu; 219 private AbstractTextSearchResult fInput; 220 private CopyToClipboardAction fCopyToClipboardAction; 222 private Action fRemoveSelectedMatches; 223 private Action fRemoveCurrentMatch; 224 private Action fRemoveAllResultsAction; 225 private Action fShowNextAction; 226 private Action fShowPreviousAction; 227 private SetLayoutAction fFlatAction; 228 private SetLayoutAction fHierarchicalAction; 229 private int fCurrentLayout; 230 private int fCurrentMatchIndex = 0; 231 private String fId; 232 private int fSupportedLayouts; 233 private SelectionProviderAdapter fViewerAdapter; 234 private SelectAllAction fSelectAllAction; 235 236 private IAction[] fFilterActions; 237 private Integer fElementLimit; 238 239 242 public static final int FLAG_LAYOUT_FLAT = 1; 243 246 public static final int FLAG_LAYOUT_TREE = 2; 247 248 249 260 protected AbstractTextSearchViewPage(int supportedLayouts) { 261 fSupportedLayouts = supportedLayouts; 262 initLayout(); 263 fRemoveAllResultsAction = new RemoveAllMatchesAction(this); 264 fRemoveSelectedMatches = new RemoveSelectedMatchesAction(this); 265 fRemoveCurrentMatch = new RemoveMatchAction(this); 266 fShowNextAction = new ShowNextResultAction(this); 267 fShowPreviousAction = new ShowPreviousResultAction(this); 268 fCopyToClipboardAction = new CopyToClipboardAction(); 269 fSelectAllAction= new SelectAllAction(); 270 createLayoutActions(); 271 fBatchedUpdates = new HashSet (); 272 fBatchedClearAll= false; 273 274 fListener = new ISearchResultListener() { 275 public void searchResultChanged(SearchResultEvent e) { 276 handleSearchResultChanged(e); 277 } 278 }; 279 fFilterActions= null; 280 fElementLimit= null; 281 } 282 283 private void initLayout() { 284 if (supportsTreeLayout()) 285 fCurrentLayout = FLAG_LAYOUT_TREE; 286 else 287 fCurrentLayout = FLAG_LAYOUT_FLAT; 288 } 289 290 295 protected AbstractTextSearchViewPage() { 296 this(FLAG_LAYOUT_FLAT | FLAG_LAYOUT_TREE); 297 } 298 299 300 private void createLayoutActions() { 301 if (countBits(fSupportedLayouts) > 1) { 302 fFlatAction = new SetLayoutAction(this, SearchMessages.AbstractTextSearchViewPage_flat_layout_label, SearchMessages.AbstractTextSearchViewPage_flat_layout_tooltip, FLAG_LAYOUT_FLAT); 303 fHierarchicalAction = new SetLayoutAction(this, SearchMessages.AbstractTextSearchViewPage_hierarchical_layout_label, SearchMessages.AbstractTextSearchViewPage_hierarchical_layout_tooltip, FLAG_LAYOUT_TREE); 304 SearchPluginImages.setImageDescriptors(fFlatAction, SearchPluginImages.T_LCL, SearchPluginImages.IMG_LCL_SEARCH_FLAT_LAYOUT); 305 SearchPluginImages.setImageDescriptors(fHierarchicalAction, SearchPluginImages.T_LCL, SearchPluginImages.IMG_LCL_SEARCH_HIERARCHICAL_LAYOUT); 306 } 307 } 308 309 private int countBits(int layoutFlags) { 310 int bitCount = 0; 311 for (int i = 0; i < 32; i++) { 312 if (layoutFlags % 2 == 1) 313 bitCount++; 314 layoutFlags >>= 1; 315 } 316 return bitCount; 317 } 318 319 private boolean supportsTreeLayout() { 320 return isLayoutSupported(FLAG_LAYOUT_TREE); 321 } 322 323 330 protected IDialogSettings getSettings() { 331 IDialogSettings parent = SearchPlugin.getDefault().getDialogSettings(); 332 IDialogSettings settings = parent.getSection(getID()); 333 if (settings == null) 334 settings = parent.addNewSection(getID()); 335 return settings; 336 } 337 338 341 public void setID(String id) { 342 fId = id; 343 } 344 345 348 public String getID() { 349 return fId; 350 } 351 352 355 public String getLabel() { 356 AbstractTextSearchResult result= getInput(); 357 if (result == null) 358 return ""; return result.getLabel(); 360 } 361 362 381 protected void showMatch(Match match, int currentOffset, int currentLength) throws PartInitException { 382 } 383 384 406 protected void showMatch(Match match, int currentOffset, int currentLength, boolean activate) throws PartInitException { 407 showMatch(match, currentOffset, currentLength); 408 } 409 410 420 protected abstract void elementsChanged(Object [] objects); 421 422 429 protected abstract void clear(); 430 431 438 protected abstract void configureTreeViewer(TreeViewer viewer); 439 440 447 protected abstract void configureTableViewer(TableViewer viewer); 448 449 455 protected void fillContextMenu(IMenuManager mgr) { 456 mgr.appendToGroup(IContextMenuConstants.GROUP_SHOW, fShowNextAction); 457 mgr.appendToGroup(IContextMenuConstants.GROUP_SHOW, fShowPreviousAction); 458 mgr.appendToGroup(IContextMenuConstants.GROUP_EDIT, fCopyToClipboardAction); 459 if (getCurrentMatch() != null) 460 mgr.appendToGroup(IContextMenuConstants.GROUP_REMOVE_MATCHES, fRemoveCurrentMatch); 461 if (canRemoveMatchesWith(getViewer().getSelection())) 462 mgr.appendToGroup(IContextMenuConstants.GROUP_REMOVE_MATCHES, fRemoveSelectedMatches); 463 mgr.appendToGroup(IContextMenuConstants.GROUP_REMOVE_MATCHES, fRemoveAllResultsAction); 464 } 465 466 470 protected boolean canRemoveMatchesWith(ISelection selection) { 471 return !selection.isEmpty(); 472 } 473 474 477 public void createControl(Composite parent) { 478 fQueryListener = createQueryListener(); 479 fMenu = new MenuManager("#PopUp"); fMenu.setRemoveAllWhenShown(true); 481 fMenu.setParent(getSite().getActionBars().getMenuManager()); 482 fMenu.addMenuListener(new IMenuListener() { 483 public void menuAboutToShow(IMenuManager mgr) { 484 SearchView.createContextMenuGroups(mgr); 485 fillContextMenu(mgr); 486 fViewPart.fillContextMenu(mgr); 487 } 488 }); 489 fPagebook = new PageBook(parent, SWT.NULL); 490 fPagebook.setLayoutData(new GridData(GridData.FILL_BOTH)); 491 fBusyLabel = createBusyControl(); 492 fViewerContainer = new Composite(fPagebook, SWT.NULL); 493 fViewerContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); 494 fViewerContainer.setSize(100, 100); 495 fViewerContainer.setLayout(new FillLayout()); 496 497 fViewerAdapter= new SelectionProviderAdapter(); 498 getSite().setSelectionProvider(fViewerAdapter); 499 getSite().registerContextMenu(fViewPart.getViewSite().getId(), fMenu, fViewerAdapter); 501 502 503 createViewer(fViewerContainer, fCurrentLayout); 504 showBusyLabel(fIsBusyShown); 505 NewSearchUI.addQueryListener(fQueryListener); 506 507 } 508 509 private Control createBusyControl() { 510 Table busyLabel = new Table(fPagebook, SWT.NONE); 511 TableItem item = new TableItem(busyLabel, SWT.NONE); 512 item.setText(SearchMessages.AbstractTextSearchViewPage_searching_label); 513 busyLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 514 return busyLabel; 515 } 516 517 private synchronized void scheduleUIUpdate() { 518 if (!fIsUIUpdateScheduled) { 519 fIsUIUpdateScheduled= true; 520 new UpdateUIJob().schedule(); 521 } 522 } 523 524 private IQueryListener createQueryListener() { 525 return new IQueryListener() { 526 public void queryAdded(ISearchQuery query) { 527 } 529 530 public void queryRemoved(ISearchQuery query) { 531 } 533 534 public void queryStarting(final ISearchQuery query) { 535 final Runnable runnable1 = new Runnable () { 536 public void run() { 537 updateBusyLabel(); 538 AbstractTextSearchResult result = getInput(); 539 540 if (result == null || !result.getQuery().equals(query)) { 541 return; 542 } 543 turnOffDecoration(); 544 scheduleUIUpdate(); 545 } 546 547 548 }; 549 asyncExec(runnable1); 550 } 551 552 public void queryFinished(final ISearchQuery query) { 553 postEnsureSelection(); 556 } 557 }; 558 } 559 560 564 protected void postEnsureSelection() { 565 fScheduleEnsureSelection= true; 566 scheduleUIUpdate(); 567 } 568 569 570 private void updateBusyLabel() { 571 AbstractTextSearchResult result = getInput(); 572 boolean shouldShowBusy = result != null && NewSearchUI.isQueryRunning(result.getQuery()) && result.getMatchCount() == 0; 573 if (shouldShowBusy == fIsBusyShown) 574 return; 575 fIsBusyShown = shouldShowBusy; 576 showBusyLabel(fIsBusyShown); 577 } 578 579 private void showBusyLabel(boolean shouldShowBusy) { 580 if (shouldShowBusy) 581 fPagebook.showPage(fBusyLabel); 582 else 583 fPagebook.showPage(fViewerContainer); 584 } 585 586 595 public boolean isLayoutSupported(int layout) { 596 return (layout & fSupportedLayouts) == layout; 597 } 598 599 608 public void setLayout(int layout) { 609 Assert.isTrue(countBits(layout) == 1); 610 Assert.isTrue(isLayoutSupported(layout)); 611 if (countBits(fSupportedLayouts) < 2) 612 return; 613 if (fCurrentLayout == layout) 614 return; 615 fCurrentLayout = layout; 616 ISelection selection = fViewer.getSelection(); 617 disconnectViewer(); 618 disposeViewer(); 619 createViewer(fViewerContainer, layout); 620 fViewerContainer.layout(true); 621 connectViewer(fInput); 622 fViewer.setSelection(selection, true); 623 getSettings().put(KEY_LAYOUT, layout); 624 getViewPart().updateLabel(); 625 } 626 627 private void disposeViewer() { 628 fViewer.removeSelectionChangedListener(fViewerAdapter); 629 fViewer.getControl().dispose(); 630 fViewer = null; 631 } 632 633 private void updateLayoutActions() { 634 if (fFlatAction != null) 635 fFlatAction.setChecked(fCurrentLayout == fFlatAction.getLayout()); 636 if (fHierarchicalAction != null) 637 fHierarchicalAction.setChecked(fCurrentLayout == fHierarchicalAction.getLayout()); 638 } 639 640 648 public int getLayout() { 649 return fCurrentLayout; 650 } 651 652 private void createViewer(Composite parent, int layout) { 653 if ((layout & FLAG_LAYOUT_FLAT) != 0) { 654 TableViewer viewer = createTableViewer(parent); 655 fViewer = viewer; 656 configureTableViewer(viewer); 657 } else if ((layout & FLAG_LAYOUT_TREE) != 0) { 658 TreeViewer viewer = createTreeViewer(parent); 659 fViewer = viewer; 660 configureTreeViewer(viewer); 661 } 662 663 fCopyToClipboardAction.setViewer(fViewer); 664 fSelectAllAction.setViewer(fViewer); 665 666 IToolBarManager tbm = getSite().getActionBars().getToolBarManager(); 667 tbm.removeAll(); 668 SearchView.createToolBarGroups(tbm); 669 fillToolbar(tbm); 670 tbm.update(false); 671 672 fViewer.addOpenListener(new IOpenListener() { 673 public void open(OpenEvent event) { 674 handleOpen(event); 675 } 676 }); 677 fViewer.addSelectionChangedListener(new ISelectionChangedListener() { 678 public void selectionChanged(SelectionChangedEvent event) { 679 fCurrentMatchIndex = -1; 680 fRemoveSelectedMatches.setEnabled(canRemoveMatchesWith(event.getSelection())); 681 } 682 }); 683 684 fViewer.addSelectionChangedListener(fViewerAdapter); 685 686 Menu menu = fMenu.createContextMenu(fViewer.getControl()); 687 fViewer.getControl().setMenu(menu); 688 689 updateLayoutActions(); 690 getViewPart().updateLabel(); 691 } 692 693 700 protected TreeViewer createTreeViewer(Composite parent) { 701 return new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); 702 } 703 704 711 protected TableViewer createTableViewer(Composite parent) { 712 return new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); 713 } 714 715 718 public void setFocus() { 719 Control control = fViewer.getControl(); 720 if (control != null && !control.isDisposed()) 721 control.setFocus(); 722 } 723 724 727 public Control getControl() { 728 return fPagebook; 729 } 730 731 734 public void setInput(ISearchResult newSearch, Object viewState) { 735 if (newSearch != null && !(newSearch instanceof AbstractTextSearchResult)) 736 return; 738 AbstractTextSearchResult oldSearch= fInput; 739 if (oldSearch != null) { 740 disconnectViewer(); 741 removeFilterActionsFromViewMenu(fFilterActions); 742 oldSearch.removeListener(fListener); 743 AnnotationManagers.removeSearchResult(getSite().getWorkbenchWindow(), oldSearch); 744 } 745 fInput= (AbstractTextSearchResult) newSearch; 746 747 if (fInput != null) { 748 AnnotationManagers.addSearchResult(getSite().getWorkbenchWindow(), fInput); 749 750 fInput.addListener(fListener); 751 connectViewer(fInput); 752 if (viewState instanceof ISelection) 753 fViewer.setSelection((ISelection) viewState, true); 754 else 755 navigateNext(true); 756 757 updateBusyLabel(); 758 turnOffDecoration(); 759 scheduleUIUpdate(); 760 761 fFilterActions= addFilterActionsToViewMenu(); 762 } 763 } 764 765 private void removeFilterActionsFromViewMenu(IAction[] filterActions) { 766 IActionBars bars= getSite().getActionBars(); 767 IMenuManager menu= bars.getMenuManager(); 768 769 if (filterActions != null) { 770 for (int i= 0; i < filterActions.length; i++) { 771 menu.remove(filterActions[i].getId()); 772 } 773 } 774 menu.remove(MatchFilterSelectionAction.ACTION_ID); 775 } 776 777 private IAction[] addFilterActionsToViewMenu() { 778 AbstractTextSearchResult input= getInput(); 779 if (input == null) { 780 return null; 781 } 782 783 MatchFilter[] allMatchFilters= input.getAllMatchFilters(); 784 if (allMatchFilters == null && getElementLimit() == null) { 785 return null; 786 } 787 788 IActionBars bars= getSite().getActionBars(); 789 IMenuManager menu= bars.getMenuManager(); 790 791 menu.prependToGroup(IContextMenuConstants.GROUP_FILTERING, new MatchFilterSelectionAction(this)); 792 793 if (allMatchFilters != null) { 794 MatchFilterAction[] actions= new MatchFilterAction[allMatchFilters.length]; 795 for (int i= allMatchFilters.length - 1; i >= 0; i--) { 796 MatchFilterAction filterAction= new MatchFilterAction(this, allMatchFilters[i]); 797 actions[i]= filterAction; 798 menu.prependToGroup(IContextMenuConstants.GROUP_FILTERING, filterAction); 799 } 800 return actions; 801 } 802 return null; 803 } 804 805 private void updateFilterActions(IAction[] filterActions) { 806 if (filterActions != null) { 807 for (int i= 0; i < filterActions.length; i++) { 808 IAction curr= filterActions[i]; 809 if (curr instanceof IUpdate) { 810 ((IUpdate) curr).update(); 811 } 812 } 813 } 814 } 815 816 819 public Object getUIState() { 820 return fViewer.getSelection(); 821 } 822 823 private void connectViewer(AbstractTextSearchResult search) { 824 fViewer.setInput(search); 825 } 826 827 private void disconnectViewer() { 828 fViewer.setInput(null); 829 } 830 831 837 protected StructuredViewer getViewer() { 838 return fViewer; 839 } 840 841 private void showMatch(final Match match, final boolean activateEditor) { 842 ISafeRunnable runnable = new ISafeRunnable() { 843 public void handleException(Throwable exception) { 844 if (exception instanceof PartInitException) { 845 PartInitException pie = (PartInitException) exception; 846 ErrorDialog.openError(getSite().getShell(), SearchMessages.DefaultSearchViewPage_show_match, SearchMessages.DefaultSearchViewPage_error_no_editor, pie.getStatus()); 847 } 848 } 849 850 public void run() throws Exception { 851 IRegion location= getCurrentMatchLocation(match); 852 showMatch(match, location.getOffset(), location.getLength(), activateEditor); 853 } 854 }; 855 SafeRunner.run(runnable); 856 } 857 858 865 public AbstractTextSearchResult getInput() { 866 return fInput; 867 } 868 869 874 public void gotoNextMatch() { 875 gotoNextMatch(false); 876 } 877 878 private void gotoNextMatch(boolean activateEditor) { 879 fCurrentMatchIndex++; 880 Match nextMatch = getCurrentMatch(); 881 if (nextMatch == null) { 882 navigateNext(true); 883 fCurrentMatchIndex = 0; 884 } 885 showCurrentMatch(activateEditor); 886 } 887 888 893 public void gotoPreviousMatch() { 894 gotoPreviousMatch(false); 895 } 896 897 private void gotoPreviousMatch(boolean activateEditor) { 898 fCurrentMatchIndex--; 899 Match nextMatch = getCurrentMatch(); 900 if (nextMatch == null) { 901 navigateNext(false); 902 fCurrentMatchIndex = getDisplayedMatchCount(getFirstSelectedElement()) - 1; 903 } 904 showCurrentMatch(activateEditor); 905 } 906 907 private void navigateNext(boolean forward) { 908 INavigate navigator = null; 909 if (fViewer instanceof TableViewer) { 910 navigator = new TableViewerNavigator((TableViewer) fViewer); 911 } else { 912 navigator = new TreeViewerNavigator(this, (TreeViewer) fViewer); 913 } 914 navigator.navigateNext(forward); 915 } 916 917 private boolean showCurrentMatch(boolean activateEditor) { 918 Match currentMatch = getCurrentMatch(); 919 if (currentMatch != null) { 920 showMatch(currentMatch, activateEditor); 921 return true; 922 } 923 return false; 924 } 925 926 931 public Match getCurrentMatch() { 932 Object element = getFirstSelectedElement(); 933 if (element != null) { 934 Match[] matches = getDisplayedMatches(element); 935 if (fCurrentMatchIndex >= 0 && fCurrentMatchIndex < matches.length) 936 return matches[fCurrentMatchIndex]; 937 } 938 return null; 939 } 940 941 956 public Match[] getDisplayedMatches(Object element) { 957 AbstractTextSearchResult result= getInput(); 958 if (result == null) 959 return EMPTY_MATCH_ARRAY; 960 Match[] matches= result.getMatches(element); 961 if (result.getActiveMatchFilters() == null) return matches; 963 964 int count= 0; 965 for (int i= 0; i < matches.length; i++) { 966 if (matches[i].isFiltered()) 967 matches[i]= null; 968 else 969 count++; 970 } 971 if (count == matches.length) 972 return matches; 973 974 Match[] filteredMatches= new Match[count]; 975 for (int i= 0, k= 0; i < matches.length; i++) { 976 if (matches[i] != null) 977 filteredMatches[k++]= matches[i]; 978 } 979 return filteredMatches; 980 } 981 982 992 public IRegion getCurrentMatchLocation(Match match) { 993 PositionTracker tracker= InternalSearchUI.getInstance().getPositionTracker(); 994 995 int offset, length; 996 Position pos= tracker.getCurrentPosition(match); 997 if (pos == null) { 998 offset= match.getOffset(); 999 length= match.getLength(); 1000 } else { 1001 offset= pos.getOffset(); 1002 length= pos.getLength(); 1003 } 1004 return new Region(offset, length); 1005 } 1006 1007 1022 public int getDisplayedMatchCount(Object element) { 1023 AbstractTextSearchResult result= getInput(); 1024 if (result == null) 1025 return 0; 1026 if (result.getActiveMatchFilters() == null) return result.getMatchCount(element); 1028 1029 int count= 0; 1030 Match[] matches= result.getMatches(element); 1031 for (int i= 0; i < matches.length; i++) { 1032 if (!matches[i].isFiltered()) 1033 count++; 1034 } 1035 return count; 1036 } 1037 1038 private Object getFirstSelectedElement() { 1039 IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); 1040 if (selection.size() > 0) 1041 return selection.getFirstElement(); 1042 return null; 1043 } 1044 1045 1048 public void dispose() { 1049 AbstractTextSearchResult oldSearch = getInput(); 1050 if (oldSearch != null) 1051 AnnotationManagers.removeSearchResult(getSite().getWorkbenchWindow(), oldSearch); 1052 super.dispose(); 1053 NewSearchUI.removeQueryListener(fQueryListener); 1054 } 1055 1056 1059 public void init(IPageSite pageSite) { 1060 super.init(pageSite); 1061 IMenuManager menuManager= pageSite.getActionBars().getMenuManager(); 1062 addLayoutActions(menuManager); 1063 initActionDefinitionIDs(pageSite.getWorkbenchWindow()); 1064 menuManager.updateAll(true); 1065 pageSite.getActionBars().updateActionBars(); 1066 } 1067 1068 private void initActionDefinitionIDs(IWorkbenchWindow window) { 1069 fCopyToClipboardAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY); 1070 fRemoveSelectedMatches.setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE); 1071 fShowNextAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_NEXT); 1072 fShowPreviousAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_PREVIOUS); 1073 fSelectAllAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL); 1074 } 1075 1076 1082 protected void fillToolbar(IToolBarManager tbm) { 1083 tbm.appendToGroup(IContextMenuConstants.GROUP_SHOW, fShowNextAction); 1084 tbm.appendToGroup(IContextMenuConstants.GROUP_SHOW, fShowPreviousAction); 1085 tbm.appendToGroup(IContextMenuConstants.GROUP_REMOVE_MATCHES, fRemoveSelectedMatches); 1086 tbm.appendToGroup(IContextMenuConstants.GROUP_REMOVE_MATCHES, fRemoveAllResultsAction); 1087 IActionBars actionBars = getSite().getActionBars(); 1088 if (actionBars != null) { 1089 actionBars.setGlobalActionHandler(ActionFactory.NEXT.getId(), fShowNextAction); 1090 actionBars.setGlobalActionHandler(ActionFactory.PREVIOUS.getId(), fShowPreviousAction); 1091 actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fRemoveSelectedMatches); 1092 actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyToClipboardAction); 1093 actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction); 1094 } 1095 if (getLayout() == FLAG_LAYOUT_TREE) { 1096 addTreeActions(tbm); 1097 } 1098 } 1099 1100 private void addTreeActions(IToolBarManager tbm) { 1101 tbm.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, new ExpandAllAction((TreeViewer)getViewer())); 1103 tbm.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, new CollapseAllAction((TreeViewer)getViewer())); 1104 } 1105 1106 private void addLayoutActions(IMenuManager menuManager) { 1107 if (fFlatAction != null) 1108 menuManager.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fFlatAction); 1109 if (fHierarchicalAction != null) 1110 menuManager.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fHierarchicalAction); 1111 } 1112 1113 1117 public void setViewPart(ISearchResultViewPart part) { 1118 fViewPart = part; 1119 } 1120 1121 1128 protected ISearchResultViewPart getViewPart() { 1129 return fViewPart; 1130 } 1131 1132 1134 1139 protected void handleSearchResultChanged(final SearchResultEvent e) { 1140 if (e instanceof MatchEvent) { 1141 postUpdate(((MatchEvent) e).getMatches()); 1142 } else if (e instanceof RemoveAllEvent) { 1143 postClear(); 1144 } else if (e instanceof FilterUpdateEvent) { 1145 postUpdate(((FilterUpdateEvent) e).getUpdatedMatches()); 1146 updateFilterActions(fFilterActions); 1147 } 1148 } 1149 1150 private synchronized void postUpdate(Match[] matches) { 1151 for (int i = 0; i < matches.length; i++) { 1152 fBatchedUpdates.add(matches[i].getElement()); 1153 } 1154 scheduleUIUpdate(); 1155 } 1156 1157 private synchronized void runBatchedUpdates() { 1158 if (false ) { 1159 Object [] hundredUpdates= new Object [50]; 1160 Iterator elements= fBatchedUpdates.iterator(); 1161 for (int i= 0; i < hundredUpdates.length; i++) { 1162 hundredUpdates[i]= elements.next(); 1163 elements.remove(); 1164 } 1165 elementsChanged(hundredUpdates); 1166 } else { 1167 elementsChanged(fBatchedUpdates.toArray()); 1168 fBatchedUpdates.clear(); 1169 } 1170 updateBusyLabel(); 1171 } 1172 1173 private synchronized void postClear() { 1174 fBatchedClearAll= true; 1175 fBatchedUpdates.clear(); 1176 scheduleUIUpdate(); 1177 } 1178 1179 private synchronized boolean hasMoreUpdates() { 1180 return fBatchedClearAll || fBatchedUpdates.size() > 0; 1181 } 1182 1183 private boolean isQueryRunning() { 1184 AbstractTextSearchResult result= getInput(); 1185 if (result != null) { 1186 return NewSearchUI.isQueryRunning(result.getQuery()); 1187 } 1188 return false; 1189 } 1190 1191 private void runBatchedClear() { 1192 synchronized(this) { 1193 if (!fBatchedClearAll) { 1194 return; 1195 } 1196 fBatchedClearAll= false; 1197 updateBusyLabel(); 1198 } 1199 getViewPart().updateLabel(); 1200 clear(); 1201 } 1202 1203 private void asyncExec(final Runnable runnable) { 1204 final Control control = getControl(); 1205 if (control != null && !control.isDisposed()) { 1206 Display currentDisplay = Display.getCurrent(); 1207 if (currentDisplay == null || !currentDisplay.equals(control.getDisplay())) 1208 control.getDisplay().asyncExec(new Runnable () { 1211 public void run() { 1212 if (!control.isDisposed()) 1213 runnable.run(); 1214 } 1215 }); 1216 else 1217 runnable.run(); 1218 } 1219 } 1220 1221 1225 public void restoreState(IMemento memento) { 1226 if (countBits(fSupportedLayouts) > 1) { 1227 try { 1228 fCurrentLayout = getSettings().getInt(KEY_LAYOUT); 1229 if (fCurrentLayout == 0) 1231 initLayout(); 1232 } catch (NumberFormatException e) { 1233 } 1235 if (memento != null) { 1236 Integer layout = memento.getInteger(KEY_LAYOUT); 1237 if (layout != null) { 1238 fCurrentLayout = layout.intValue(); 1239 if (fCurrentLayout == 0) 1241 initLayout(); 1242 } 1243 } 1244 } 1245 } 1246 1247 1250 public void saveState(IMemento memento) { 1251 if (countBits(fSupportedLayouts) > 1) { 1252 memento.putInteger(KEY_LAYOUT, fCurrentLayout); 1253 } 1254 } 1255 1256 1264 public void internalRemoveSelected() { 1265 AbstractTextSearchResult result = getInput(); 1266 if (result == null) 1267 return; 1268 StructuredViewer viewer = getViewer(); 1269 IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); 1270 HashSet set = new HashSet (); 1271 if (viewer instanceof TreeViewer) { 1272 ITreeContentProvider cp = (ITreeContentProvider) viewer.getContentProvider(); 1273 collectAllMatchesBelow(result, set, cp, selection.toArray()); 1274 } else { 1275 collectAllMatches(set, selection.toArray()); 1276 } 1277 Match[] matches = new Match[set.size()]; 1278 set.toArray(matches); 1279 result.removeMatches(matches); 1280 } 1281 1282 private void collectAllMatches(HashSet set, Object [] elements) { 1283 for (int j = 0; j < elements.length; j++) { 1284 Match[] matches = getDisplayedMatches(elements[j]); 1285 for (int i = 0; i < matches.length; i++) { 1286 set.add(matches[i]); 1287 } 1288 } 1289 } 1290 1291 private void collectAllMatchesBelow(AbstractTextSearchResult result, Set set, ITreeContentProvider cp, Object [] elements) { 1292 for (int j = 0; j < elements.length; j++) { 1293 Match[] matches = getDisplayedMatches(elements[j]); 1294 for (int i = 0; i < matches.length; i++) { 1295 set.add(matches[i]); 1296 } 1297 Object [] children = cp.getChildren(elements[j]); 1298 collectAllMatchesBelow(result, set, cp, children); 1299 } 1300 } 1301 1302 private void turnOffDecoration() { 1303 IBaseLabelProvider lp= fViewer.getLabelProvider(); 1304 if (lp instanceof DecoratingLabelProvider) { 1305 ((DecoratingLabelProvider)lp).setLabelDecorator(null); 1306 } 1307 } 1308 1309 private void turnOnDecoration() { 1310 IBaseLabelProvider lp= fViewer.getLabelProvider(); 1311 if (lp instanceof DecoratingLabelProvider) { 1312 ((DecoratingLabelProvider)lp).setLabelDecorator(PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()); 1313 1314 } 1315 } 1316 1317 1330 protected void handleOpen(OpenEvent event) { 1331 Viewer viewer= event.getViewer(); 1332 boolean hasCurrentMatch = showCurrentMatch(OpenStrategy.activateOnOpen()); 1333 ISelection sel= event.getSelection(); 1334 if (viewer instanceof TreeViewer && sel instanceof IStructuredSelection) { 1335 IStructuredSelection selection= (IStructuredSelection) sel; 1336 TreeViewer tv = (TreeViewer) getViewer(); 1337 Object element = selection.getFirstElement(); 1338 if (element != null) { 1339 if (!hasCurrentMatch && getDisplayedMatchCount(element) > 0) 1340 gotoNextMatch(OpenStrategy.activateOnOpen()); 1341 else 1342 tv.setExpandedState(element, !tv.getExpandedState(element)); 1343 } 1344 return; 1345 } else if (!hasCurrentMatch) { 1346 gotoNextMatch(OpenStrategy.activateOnOpen()); 1347 } 1348 } 1349 1350 1367 public void setElementLimit(Integer limit) { 1368 fElementLimit= limit; 1369 1370 if (fViewer != null) { 1371 fViewer.refresh(); 1372 } 1373 if (fViewPart != null) { 1374 fViewPart.updateLabel(); 1375 } 1376 } 1377 1378 1393 public Integer getElementLimit() { 1394 return fElementLimit; 1395 } 1396 1397 1398} 1399 | Popular Tags |