1 12 13 package org.eclipse.ui.texteditor; 14 15 import java.util.Stack ; 16 17 import org.eclipse.swt.SWT; 18 import org.eclipse.swt.custom.StyledText; 19 import org.eclipse.swt.custom.VerifyKeyListener; 20 import org.eclipse.swt.events.FocusEvent; 21 import org.eclipse.swt.events.FocusListener; 22 import org.eclipse.swt.events.MouseEvent; 23 import org.eclipse.swt.events.MouseListener; 24 import org.eclipse.swt.events.VerifyEvent; 25 import org.eclipse.swt.graphics.Color; 26 import org.eclipse.swt.graphics.Point; 27 28 import org.eclipse.core.commands.ExecutionEvent; 29 import org.eclipse.core.commands.ExecutionException; 30 import org.eclipse.core.commands.IExecutionListener; 31 import org.eclipse.core.commands.NotHandledException; 32 33 import org.eclipse.core.runtime.Assert; 34 35 import org.eclipse.jface.action.IStatusLineManager; 36 import org.eclipse.jface.viewers.ISelection; 37 import org.eclipse.jface.viewers.ISelectionChangedListener; 38 import org.eclipse.jface.viewers.ISelectionProvider; 39 import org.eclipse.jface.viewers.SelectionChangedEvent; 40 41 import org.eclipse.jface.text.IFindReplaceTarget; 42 import org.eclipse.jface.text.IFindReplaceTargetExtension; 43 import org.eclipse.jface.text.IRegion; 44 import org.eclipse.jface.text.ITextListener; 45 import org.eclipse.jface.text.ITextSelection; 46 import org.eclipse.jface.text.ITextViewer; 47 import org.eclipse.jface.text.ITextViewerExtension; 48 import org.eclipse.jface.text.TextEvent; 49 50 import org.eclipse.ui.PlatformUI; 51 import org.eclipse.ui.commands.ICommandService; 52 import org.eclipse.ui.internal.texteditor.NLSUtility; 53 54 58 class IncrementalFindTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, VerifyKeyListener, MouseListener, FocusListener, ISelectionChangedListener, ITextListener, IExecutionListener { 59 60 61 private final static String TAB= EditorMessages.Editor_FindIncremental_render_tab; 62 66 private final static String FIELD_NAME= EditorMessages.Editor_FindIncremental_name; 67 71 private final static String REVERSE_FIELD_NAME= EditorMessages.Editor_FindIncremental_reverse_name; 72 76 private final static String REVERSE= EditorMessages.Editor_FindIncremental_reverse; 77 81 private final static String WRAPPED= EditorMessages.Editor_FindIncremental_wrapped; 82 83 private final ITextViewer fTextViewer; 84 85 private final IStatusLineManager fStatusLine; 86 87 private final IFindReplaceTarget fTarget; 88 89 private StringBuffer fFindString= new StringBuffer (); 90 91 private int fCasePosition; 92 96 private int fWrapPosition; 97 98 private int fCurrentIndex; 99 100 private boolean fFound; 101 105 private boolean fForward= true; 106 107 private boolean fInstalled; 108 113 private boolean fSearching; 114 115 private Stack fSessionStack; 116 120 private String fPrevFindString= ""; 125 private int fPrevCasePosition= -1; 126 130 private IStatusField fStatusField; 131 137 private boolean fIsStatusFieldExtension; 138 139 143 private class SearchResult { 144 int selection, length, index, findLength; 145 boolean found, forward; 146 147 151 public SearchResult() { 152 Point p= fTarget.getSelection(); 153 selection= p.x; 154 length= p.y; 155 index= fCurrentIndex; 156 findLength= fFindString.length(); 157 found= fFound; 158 forward= fForward; 159 } 160 161 } 162 163 166 private void saveState() { 167 fSessionStack.push(new SearchResult()); 168 } 169 170 175 private void restoreState() { 176 177 StyledText text= fTextViewer.getTextWidget(); 178 if (text == null || text.isDisposed()) 179 return; 180 181 SearchResult searchResult= null; 182 if (!fSessionStack.empty()) 183 searchResult= (SearchResult) fSessionStack.pop(); 184 185 if (searchResult == null) { 186 text.getDisplay().beep(); 187 return; 188 } 189 190 text.setSelectionRange(searchResult.selection, searchResult.length); 191 text.showSelection(); 192 193 fFindString.setLength(searchResult.findLength); 195 fCurrentIndex= searchResult.index; 196 fFound= searchResult.found; 197 fForward= searchResult.forward; 198 199 if (fFindString.length() <= fCasePosition) 201 fCasePosition= -1; 202 if (fSessionStack.size() < fWrapPosition) 203 fWrapPosition= -1; 204 } 205 206 213 public void setDirection(boolean forward) { 214 fForward= forward; 215 } 216 217 222 public IncrementalFindTarget(ITextViewer viewer, IStatusLineManager manager) { 223 Assert.isNotNull(viewer); 224 Assert.isNotNull(manager); 225 fTextViewer= viewer; 226 fStatusLine= manager; 227 fTarget= viewer.getFindReplaceTarget(); 228 } 229 230 233 public boolean canPerformFind() { 234 return fTarget.canPerformFind(); 235 } 236 237 240 public int findAndSelect(int offset, String findString, boolean searchForward, boolean caseSensitive, boolean wholeWord) { 241 return fTarget.findAndSelect(offset, findString, searchForward, caseSensitive, wholeWord); 242 } 243 244 247 public Point getSelection() { 248 return fTarget.getSelection(); 249 } 250 251 254 public String getSelectionText() { 255 return fTarget.getSelectionText(); 256 } 257 258 261 public boolean isEditable() { 262 return false; 263 } 264 265 268 public void replaceSelection(String text) { 269 } 270 271 274 public void beginSession() { 275 fSearching= true; 276 277 if (fInstalled) { 279 saveState(); 280 repeatSearch(fForward); 281 updateStatus(); 282 fSearching= false; 283 return; 284 } 285 286 fFindString.setLength(0); 287 fSessionStack= new Stack (); 288 fCasePosition= -1; 289 fWrapPosition= -1; 290 fFound= true; 291 292 StyledText text= fTextViewer.getTextWidget(); 294 if (text != null && !text.isDisposed()) { 295 fCurrentIndex= text.getCaretOffset(); 296 text.setSelection(fCurrentIndex); 297 } else { 298 fCurrentIndex= 0; 299 } 300 301 install(); 302 303 if (fTextViewer instanceof ITextViewerExtension) 305 ((ITextViewerExtension) fTextViewer).setMark(fCurrentIndex); 306 307 updateStatus(); 308 309 if (fTarget instanceof IFindReplaceTargetExtension) 310 ((IFindReplaceTargetExtension) fTarget).beginSession(); 311 312 fSearching= false; 313 } 314 315 318 public void endSession() { 319 if (fTarget instanceof IFindReplaceTargetExtension) 320 ((IFindReplaceTargetExtension) fTarget).endSession(); 321 322 } 324 325 328 public IRegion getScope() { 329 return null; 330 } 331 332 335 public void setGlobal(boolean global) { 336 } 337 338 341 public void setScope(IRegion scope) { 342 } 343 344 347 public void setReplaceAllMode(boolean replaceAll) { 348 } 349 350 353 private void install() { 354 355 if (fInstalled) 356 return; 357 358 StyledText text= fTextViewer.getTextWidget(); 359 if (text == null) 360 return; 361 362 text.addMouseListener(this); 363 text.addFocusListener(this); 364 fTextViewer.addTextListener(this); 365 366 ISelectionProvider selectionProvider= fTextViewer.getSelectionProvider(); 367 if (selectionProvider != null) 368 selectionProvider.addSelectionChangedListener(this); 369 370 if (fTextViewer instanceof ITextViewerExtension) 371 ((ITextViewerExtension) fTextViewer).prependVerifyKeyListener(this); 372 else 373 text.addVerifyKeyListener(this); 374 375 ICommandService commandService= (ICommandService)PlatformUI.getWorkbench().getAdapter(ICommandService.class); 376 if (commandService != null) 377 commandService.addExecutionListener(this); 378 379 fInstalled= true; 380 } 381 382 385 private void uninstall() { 386 387 fTextViewer.removeTextListener(this); 388 389 ISelectionProvider selectionProvider= fTextViewer.getSelectionProvider(); 390 if (selectionProvider != null) 391 selectionProvider.removeSelectionChangedListener(this); 392 393 StyledText text= fTextViewer.getTextWidget(); 394 if (text != null) { 395 text.removeMouseListener(this); 396 text.removeFocusListener(this); 397 } 398 399 if (fTextViewer instanceof ITextViewerExtension) { 400 ((ITextViewerExtension) fTextViewer).removeVerifyKeyListener(this); 401 402 } else { 403 if (text != null) 404 text.removeVerifyKeyListener(this); 405 } 406 407 ICommandService commandService= (ICommandService)PlatformUI.getWorkbench().getAdapter(ICommandService.class); 408 if (commandService != null) 409 commandService.removeExecutionListener(this); 410 411 fInstalled= false; 412 } 413 414 418 private void updateStatus() { 419 420 if (!fInstalled) 421 return; 422 423 String string= fFindString.toString(); 424 String wrapPrefix= fWrapPosition == -1 ? "" : WRAPPED; String reversePrefix= fForward ? "" : REVERSE; 427 if (!fFound) { 428 String pattern= EditorMessages.Editor_FindIncremental_not_found_pattern; 429 statusError(NLSUtility.format(pattern, new Object [] { reversePrefix, wrapPrefix, string })); 430 431 } else if (string.length() == 0) { 432 if (fForward) 433 statusMessage(FIELD_NAME); 434 else 435 statusMessage(REVERSE_FIELD_NAME); 436 } else if (!fForward || fWrapPosition > -1) { 437 String pattern= EditorMessages.Editor_FindIncremental_found_pattern; 438 statusMessage(NLSUtility.format(pattern, new Object [] { reversePrefix, wrapPrefix, string })); 439 } else { 440 statusMessage(string); 441 } 442 } 443 444 447 public void verifyKey(VerifyEvent event) { 448 449 if (!event.doit) 450 return; 451 452 fSearching= true; 453 if (event.character == 0) { 454 455 switch (event.keyCode) { 456 457 case SWT.ARROW_LEFT: 459 case SWT.ARROW_RIGHT: 460 case SWT.HOME: 461 case SWT.END: 462 case SWT.PAGE_DOWN: 463 case SWT.PAGE_UP: 464 leave(); 465 break; 466 467 case SWT.ARROW_DOWN: 468 saveState(); 469 setDirection(true); 470 repeatSearch(fForward); 471 event.doit= false; 472 break; 473 474 case SWT.ARROW_UP: 475 saveState(); 476 setDirection(false); 477 repeatSearch(fForward); 478 event.doit= false; 479 break; 480 } 481 482 } else { 484 485 switch (event.character) { 486 487 case 0x1B: 489 case 0x0D: 490 leave(); 491 event.doit= false; 492 break; 493 494 case 0x08: 496 case 0x7F: 497 restoreState(); 498 event.doit= false; 499 break; 500 501 default: 502 if (event.stateMask == 0 || event.stateMask == SWT.SHIFT || event.stateMask == (SWT.ALT | SWT.CTRL)) { saveState(); 504 addCharSearch(event.character); 505 event.doit= false; 506 } 507 break; 508 } 509 } 510 updateStatus(); 511 fSearching= false; 512 } 513 514 521 private boolean repeatSearch(boolean forward) { 522 if (fFindString.length() == 0) { 523 fFindString= new StringBuffer (fPrevFindString); 524 fCasePosition= fPrevCasePosition; 525 } 526 527 String string= fFindString.toString(); 528 if (string.length() == 0) { 529 fFound= true; 530 return true; 531 } 532 533 StyledText text= fTextViewer.getTextWidget(); 534 int startIndex= text.getCaretOffset(); 537 if (!forward) 538 startIndex -= 1; 539 540 if (!fFound && (fForward == forward)) { 542 startIndex= -1; 543 if (fWrapPosition == -1) 544 fWrapPosition= fSessionStack.size(); 545 } 546 fForward = forward; 547 548 text.setRedraw(false); 550 int index= fTarget.findAndSelect(startIndex, string, fForward, fCasePosition != -1, false); 551 552 if (!forward) { 554 Point p= fTarget.getSelection(); 555 text.setSelectionRange(p.x + p.y, -p.y); 556 p= null; 557 } 558 text.setRedraw(true); 559 560 boolean found = (index != -1); 562 if (!found && fFound) { 563 text= fTextViewer.getTextWidget(); 564 if (text != null && !text.isDisposed()) 565 text.getDisplay().beep(); 566 } 567 568 if (found) 569 fCurrentIndex= startIndex; 570 571 fFound= found; 572 return found; 573 } 574 575 582 private boolean addCharSearch(char c) { 583 if (fCasePosition == -1 && Character.isUpperCase(c) && Character.toLowerCase(c) != c) 585 fCasePosition= fFindString.length(); 586 587 fFindString.append(c); 588 String string= fFindString.toString(); 589 StyledText text= fTextViewer.getTextWidget(); 590 591 text.setRedraw(false); 592 int index= fTarget.findAndSelect(fCurrentIndex, string, fForward, fCasePosition != -1, false); 593 594 if (!fForward) { 596 Point p= fTarget.getSelection(); 597 text.setSelectionRange(p.x + p.y, -p.y); 598 } 599 text.setRedraw(true); 600 601 boolean found = (index != -1); 603 if (!found && fFound) { 604 text= fTextViewer.getTextWidget(); 605 if (text != null && !text.isDisposed()) 606 text.getDisplay().beep(); 607 } 608 609 fFound= found; 610 return found; 611 } 612 613 616 private void leave() { 617 if (fFindString.length() != 0) { 618 fPrevFindString= fFindString.toString(); 619 fPrevCasePosition= fCasePosition; 620 } 621 statusClear(); 622 uninstall(); 623 fSessionStack = null; 624 } 625 626 629 public void textChanged(TextEvent event) { 630 if (event.getDocumentEvent() != null) 631 leave(); 632 } 633 634 637 public void mouseDoubleClick(MouseEvent e) { 638 leave(); 639 } 640 641 644 public void mouseDown(MouseEvent e) { 645 leave(); 646 } 647 648 651 public void mouseUp(MouseEvent e) { 652 leave(); 653 } 654 655 658 public void focusGained(FocusEvent e) { 659 leave(); 660 } 661 662 665 public void focusLost(FocusEvent e) { 666 leave(); 667 } 668 669 673 private void statusMessage(String string) { 674 if (fStatusField != null) { 675 if (fIsStatusFieldExtension) { 676 ((IStatusFieldExtension)fStatusField).setErrorText(null); 677 fStatusField.setText(escapeTabs(string)); 678 ((IStatusFieldExtension)fStatusField).setVisible(true); 679 fStatusLine.update(true); 680 } else { 681 fStatusLine.setErrorMessage(null); 682 fStatusField.setText(escapeTabs(string)); 683 } 684 } else { 685 fStatusLine.setErrorMessage(null); 686 fStatusLine.setMessage(escapeTabs(string)); 687 } 688 } 689 690 694 private void statusError(String string) { 695 if (fStatusField != null) { 696 if (fIsStatusFieldExtension) { 697 ((IStatusFieldExtension)fStatusField).setErrorText(escapeTabs(string)); 698 fStatusField.setText(""); ((IStatusFieldExtension)fStatusField).setVisible(true); 700 fStatusLine.update(true); 701 } else { 702 fStatusLine.setErrorMessage(escapeTabs(string)); 703 fStatusField.setText(""); } 705 } else { 706 fStatusLine.setErrorMessage(escapeTabs(string)); 707 fStatusLine.setMessage(null); 708 } 709 } 710 711 714 private void statusClear() { 715 if (fStatusField != null) { 716 if (fIsStatusFieldExtension) { 717 fStatusField.setText(""); ((IStatusFieldExtension)fStatusField).setErrorText(null); 719 ((IStatusFieldExtension)fStatusField).setVisible(false); 720 fStatusLine.update(true); 721 } else { 722 fStatusField.setText(""); fStatusLine.setErrorMessage(null); 724 } 725 } else { 726 fStatusLine.setErrorMessage(null); 727 fStatusLine.setMessage(null); 728 } 729 } 730 731 736 private String escapeTabs(String string) { 737 StringBuffer buffer= new StringBuffer (); 738 739 int begin= 0; 740 int end= string.indexOf('\t', begin); 741 742 while (end >= 0) { 743 buffer.append(string.substring(begin, end)); 744 buffer.append(TAB); 745 begin= end + 1; 746 end= string.indexOf('\t', begin); 747 } 748 buffer.append(string.substring(begin)); 749 750 return buffer.toString(); 751 } 752 753 756 public Point getLineSelection() { 757 if (fTarget instanceof IFindReplaceTargetExtension) 758 return ((IFindReplaceTargetExtension) fTarget).getLineSelection(); 759 760 return null; } 762 763 766 public void setSelection(int offset, int length) { 767 if (fTarget instanceof IFindReplaceTargetExtension) 768 ((IFindReplaceTargetExtension) fTarget).setSelection(offset, length); 769 } 770 771 774 public void setScopeHighlightColor(Color color) { 775 } 776 777 781 public void selectionChanged(SelectionChangedEvent e) { 782 boolean ignore= false; 783 ISelection selection= e.getSelection(); 784 if (selection instanceof ITextSelection) { 785 ITextSelection textSelection= (ITextSelection)selection; 786 Point range= getSelection(); 787 ignore= textSelection.getOffset() + textSelection.getLength() == range.x + range.y; 788 } 789 if (!fSearching && !ignore) 790 leave(); 791 } 792 793 799 void setStatusField(IStatusField statusField) { 800 fStatusField= statusField; 801 fIsStatusFieldExtension= fStatusField instanceof IStatusFieldExtension; 802 } 803 804 808 public void notHandled(String commandId, NotHandledException exception) { 809 } 810 811 815 public void postExecuteFailure(String commandId, ExecutionException exception) { 816 } 817 818 822 public void postExecuteSuccess(String commandId, Object returnValue) { 823 } 824 825 829 public void preExecute(String commandId, ExecutionEvent event) { 830 if (IWorkbenchActionDefinitionIds.FIND_INCREMENTAL.equals(commandId) 831 || IWorkbenchActionDefinitionIds.FIND_INCREMENTAL_REVERSE.equals(commandId)) 832 return; 833 leave(); 834 } 835 } 836 | Popular Tags |