1 11 package org.eclipse.jface.text.link; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Set ; 19 20 import org.eclipse.swt.SWT; 21 import org.eclipse.swt.custom.StyledText; 22 import org.eclipse.swt.custom.VerifyKeyListener; 23 import org.eclipse.swt.events.ShellEvent; 24 import org.eclipse.swt.events.ShellListener; 25 import org.eclipse.swt.events.VerifyEvent; 26 import org.eclipse.swt.graphics.Point; 27 import org.eclipse.swt.widgets.Display; 28 import org.eclipse.swt.widgets.Shell; 29 30 import org.eclipse.core.runtime.Assert; 31 32 import org.eclipse.jface.internal.text.link.contentassist.ContentAssistant2; 33 import org.eclipse.jface.internal.text.link.contentassist.IProposalListener; 34 import org.eclipse.jface.viewers.IPostSelectionProvider; 35 import org.eclipse.jface.viewers.ISelection; 36 import org.eclipse.jface.viewers.ISelectionChangedListener; 37 import org.eclipse.jface.viewers.SelectionChangedEvent; 38 39 import org.eclipse.jface.text.BadLocationException; 40 import org.eclipse.jface.text.BadPartitioningException; 41 import org.eclipse.jface.text.BadPositionCategoryException; 42 import org.eclipse.jface.text.DefaultPositionUpdater; 43 import org.eclipse.jface.text.DocumentCommand; 44 import org.eclipse.jface.text.DocumentEvent; 45 import org.eclipse.jface.text.IAutoEditStrategy; 46 import org.eclipse.jface.text.IDocument; 47 import org.eclipse.jface.text.IDocumentExtension3; 48 import org.eclipse.jface.text.IDocumentListener; 49 import org.eclipse.jface.text.IEditingSupport; 50 import org.eclipse.jface.text.IEditingSupportRegistry; 51 import org.eclipse.jface.text.IPositionUpdater; 52 import org.eclipse.jface.text.IRegion; 53 import org.eclipse.jface.text.IRewriteTarget; 54 import org.eclipse.jface.text.ITextInputListener; 55 import org.eclipse.jface.text.ITextOperationTarget; 56 import org.eclipse.jface.text.ITextSelection; 57 import org.eclipse.jface.text.ITextViewer; 58 import org.eclipse.jface.text.ITextViewerExtension; 59 import org.eclipse.jface.text.ITextViewerExtension2; 60 import org.eclipse.jface.text.ITextViewerExtension5; 61 import org.eclipse.jface.text.Position; 62 import org.eclipse.jface.text.Region; 63 import org.eclipse.jface.text.contentassist.ICompletionProposal; 64 import org.eclipse.jface.text.source.IAnnotationModel; 65 import org.eclipse.jface.text.source.IAnnotationModelExtension; 66 import org.eclipse.jface.text.source.ISourceViewer; 67 68 83 public class LinkedModeUI { 84 85 86 90 public static final Object CYCLE_NEVER= new Object (); 91 95 public static final Object CYCLE_ALWAYS= new Object (); 96 100 public static final Object CYCLE_WHEN_NO_PARENT= new Object (); 101 102 108 public interface ILinkedModeUIFocusListener { 109 115 void linkingFocusLost(LinkedPosition position, LinkedModeUITarget target); 116 122 void linkingFocusGained(LinkedPosition position, LinkedModeUITarget target); 123 } 124 125 128 private static final class EmtpyFocusListener implements ILinkedModeUIFocusListener { 129 130 public void linkingFocusGained(LinkedPosition position, LinkedModeUITarget target) { 131 } 133 134 public void linkingFocusLost(LinkedPosition position, LinkedModeUITarget target) { 135 } 137 } 138 139 147 public static abstract class LinkedModeUITarget implements ILinkedModeUIFocusListener { 148 153 public abstract ITextViewer getViewer(); 154 155 162 StyledText fWidget; 163 164 165 Shell fShell; 166 167 168 KeyListener fKeyListener; 169 170 171 LinkedPositionAnnotations fAnnotationModel; 172 } 173 174 private static final class EmptyTarget extends LinkedModeUITarget { 175 176 private ITextViewer fTextViewer; 177 178 181 public EmptyTarget(ITextViewer viewer) { 182 Assert.isNotNull(viewer); 183 fTextViewer= viewer; 184 } 185 186 189 public ITextViewer getViewer() { 190 return fTextViewer; 191 } 192 193 196 public void linkingFocusLost(LinkedPosition position, LinkedModeUITarget target) { 197 } 198 199 202 public void linkingFocusGained(LinkedPosition position, LinkedModeUITarget target) { 203 } 204 205 } 206 207 210 private final class ExitListener implements ILinkedModeListener { 211 public void left(LinkedModeModel model, int flags) { 212 leave(ILinkedModeListener.EXIT_ALL | flags); 213 } 214 215 public void suspend(LinkedModeModel model) { 216 disconnect(); 217 redraw(); 218 } 219 220 public void resume(LinkedModeModel model, int flags) { 221 if ((flags & ILinkedModeListener.EXIT_ALL) != 0) { 222 leave(flags); 223 } else { 224 connect(); 225 if ((flags & ILinkedModeListener.SELECT) != 0) 226 select(); 227 ensureAnnotationModelInstalled(); 228 redraw(); 229 } 230 } 231 } 232 233 239 public static class ExitFlags { 240 241 public int flags; 242 243 public boolean doit; 244 250 public ExitFlags(int flags, boolean doit) { 251 this.flags= flags; 252 this.doit= doit; 253 } 254 } 255 256 263 public interface IExitPolicy { 264 277 ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length); 278 } 279 280 283 private static class NullExitPolicy implements IExitPolicy { 284 287 public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) { 288 return null; 289 } 290 } 291 292 295 private class Closer implements ShellListener, ITextInputListener { 296 297 public void shellActivated(ShellEvent e) { 298 } 299 300 public void shellClosed(ShellEvent e) { 301 leave(ILinkedModeListener.EXIT_ALL); 302 } 303 304 public void shellDeactivated(ShellEvent e) { 305 308 310 314 317 321 StyledText text; 322 final ITextViewer viewer; 323 Display display; 324 325 if (fCurrentTarget == null || (text= fCurrentTarget.fWidget) == null 326 || text.isDisposed() || (display= text.getDisplay()) == null 327 || display.isDisposed() 328 || (viewer= fCurrentTarget.getViewer()) == null) 329 { 330 leave(ILinkedModeListener.EXIT_ALL); 331 } 332 else 333 { 334 display.asyncExec(new Runnable () { 336 public void run() { 337 if (fIsActive && viewer instanceof IEditingSupportRegistry) { 338 IEditingSupport[] helpers= ((IEditingSupportRegistry) viewer).getRegisteredSupports(); 339 for (int i= 0; i < helpers.length; i++) { 340 if (helpers[i].ownsFocusShell()) 341 return; 342 } 343 } 344 345 leave(ILinkedModeListener.EXIT_ALL); 347 348 } 349 }); 350 } 351 } 352 353 public void shellDeiconified(ShellEvent e) { 354 } 355 356 public void shellIconified(ShellEvent e) { 357 leave(ILinkedModeListener.EXIT_ALL); 358 } 359 360 363 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 364 leave(ILinkedModeListener.EXIT_ALL); 365 } 366 367 370 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 371 } 372 373 } 374 375 378 private class DocumentListener implements IDocumentListener { 379 382 public void documentAboutToBeChanged(DocumentEvent event) { 383 384 int end= event.getOffset() + event.getLength(); 387 for (int offset= event.getOffset(); offset <= end; offset++) { 388 if (!fModel.anyPositionContains(offset)) { 389 ITextViewer viewer= fCurrentTarget.getViewer(); 390 if (fFramePosition != null && viewer instanceof IEditingSupportRegistry) { 391 IEditingSupport[] helpers= ((IEditingSupportRegistry) viewer).getRegisteredSupports(); 392 for (int i= 0; i < helpers.length; i++) { 393 if (helpers[i].isOriginator(null, new Region(fFramePosition.getOffset(), fFramePosition.getLength()))) 394 return; 395 } 396 } 397 398 leave(ILinkedModeListener.EXTERNAL_MODIFICATION); 399 return; 400 } 401 } 402 } 403 404 407 public void documentChanged(DocumentEvent event) { 408 } 409 } 410 411 415 private class KeyListener implements VerifyKeyListener { 416 417 private boolean fIsEnabled= true; 418 419 public void verifyKey(VerifyEvent event) { 420 421 if (!event.doit || !fIsEnabled) 422 return; 423 424 Point selection= fCurrentTarget.getViewer().getSelectedRange(); 425 int offset= selection.x; 426 int length= selection.y; 427 428 ExitFlags exitFlags= fExitPolicy.doExit(fModel, event, offset, length); 430 if (exitFlags != null) { 431 leave(exitFlags.flags); 432 event.doit= exitFlags.doit; 433 return; 434 } 435 436 switch (event.character) { 444 case 0x09: 446 if (!(fExitPosition != null && fExitPosition.includes(offset)) && !fModel.anyPositionContains(offset)) { 447 leave(ILinkedModeListener.EXIT_ALL); 449 break; 450 } 451 452 if (event.stateMask == SWT.SHIFT) 453 previous(); 454 else 455 next(); 456 457 event.doit= false; 458 break; 459 460 case 0x0A: 462 case 0x0D: 464 if (!fModel.anyPositionContains(offset)) { 466 leave(ILinkedModeListener.EXIT_ALL); 469 break; 470 } 471 472 leave(ILinkedModeListener.EXIT_ALL | ILinkedModeListener.UPDATE_CARET); 474 event.doit= false; 475 break; 476 477 case 0x1B: 479 leave(ILinkedModeListener.EXIT_ALL); 481 event.doit= false; 482 break; 483 484 default: 485 if (event.character != 0) { 486 if (!controlUndoBehavior(offset, length)) { 487 leave(ILinkedModeListener.EXIT_ALL); 488 break; 489 } 490 } 491 } 492 } 493 494 private boolean controlUndoBehavior(int offset, int length) { 495 LinkedPosition position= fModel.findPosition(new LinkedPosition(fCurrentTarget.getViewer().getDocument(), offset, length, LinkedPositionGroup.NO_STOP)); 496 if (position != null) { 497 498 if (!position.equals(fPreviousPosition)) 500 endCompoundChange(); 501 502 beginCompoundChange(); 503 } 504 505 fPreviousPosition= position; 506 return fPreviousPosition != null; 507 } 508 509 512 public void setEnabled(boolean enabled) { 513 fIsEnabled= enabled; 514 } 515 516 } 517 518 523 private class MySelectionListener implements ISelectionChangedListener { 524 525 528 public void selectionChanged(SelectionChangedEvent event) { 529 ISelection selection= event.getSelection(); 530 if (selection instanceof ITextSelection) { 531 ITextSelection textsel= (ITextSelection) selection; 532 if (event.getSelectionProvider() instanceof ITextViewer) { 533 IDocument doc= ((ITextViewer) event.getSelectionProvider()).getDocument(); 534 if (doc != null) { 535 int offset= textsel.getOffset(); 536 int length= textsel.getLength(); 537 if (offset >= 0 && length >= 0) { 538 LinkedPosition find= new LinkedPosition(doc, offset, length, LinkedPositionGroup.NO_STOP); 539 LinkedPosition pos= fModel.findPosition(find); 540 if (pos == null && fExitPosition != null && fExitPosition.includes(find)) 541 pos= fExitPosition; 542 543 if (pos != null) 544 switchPosition(pos, false, false); 545 } 546 } 547 } 548 } 549 } 550 551 } 552 553 private class ProposalListener implements IProposalListener { 554 555 558 public void proposalChosen(ICompletionProposal proposal) { 559 next(); 560 } 561 } 562 563 564 private LinkedModeUITarget fCurrentTarget; 565 569 private LinkedModeModel fModel; 570 571 private LinkedModeUITarget[] fTargets; 572 573 private TabStopIterator fIterator; 574 575 576 577 private Closer fCloser= new Closer(); 578 579 private ILinkedModeListener fLinkedListener= new ExitListener(); 580 581 private MySelectionListener fSelectionListener= new MySelectionListener(); 582 583 private ProposalListener fProposalListener= new ProposalListener(); 584 588 private IDocumentListener fDocumentListener= new DocumentListener(); 589 590 591 private final Position fCaretPosition= new Position(0, 0); 592 593 private IExitPolicy fExitPolicy= new NullExitPolicy(); 594 595 private LinkedPosition fFramePosition; 596 597 private LinkedPosition fPreviousPosition; 598 599 private ContentAssistant2 fAssistant; 600 601 private LinkedPosition fExitPosition; 602 603 private boolean fIsActive= false; 604 605 private IPositionUpdater fPositionUpdater= new DefaultPositionUpdater(getCategory()); 606 607 private boolean fDoContextInfo= false; 608 609 private boolean fHasOpenCompoundChange= false; 610 611 private ILinkedModeUIFocusListener fPositionListener= new EmtpyFocusListener(); 612 private IAutoEditStrategy fAutoEditVetoer= new IAutoEditStrategy() { 613 614 617 public void customizeDocumentCommand(IDocument document, DocumentCommand command) { 618 if (fModel.anyPositionContains(command.offset)) { 620 command.doit= false; 621 command.caretOffset= command.offset + command.length; 622 } 623 624 } 625 }; 626 627 private boolean fSimple; 628 629 637 public LinkedModeUI(LinkedModeModel model, LinkedModeUITarget[] targets) { 638 constructor(model, targets); 639 } 640 641 647 public LinkedModeUI(LinkedModeModel model, ITextViewer viewer) { 648 constructor(model, new LinkedModeUITarget[]{new EmptyTarget(viewer)}); 649 } 650 651 658 public LinkedModeUI(LinkedModeModel model, ITextViewer[] viewers) { 659 LinkedModeUITarget[] array= new LinkedModeUITarget[viewers.length]; 660 for (int i= 0; i < array.length; i++) { 661 array[i]= new EmptyTarget(viewers[i]); 662 } 663 constructor(model, array); 664 } 665 666 672 public LinkedModeUI(LinkedModeModel model, LinkedModeUITarget target) { 673 constructor(model, new LinkedModeUITarget[]{target}); 674 } 675 676 683 private void constructor(LinkedModeModel model, LinkedModeUITarget[] targets) { 684 Assert.isNotNull(model); 685 Assert.isNotNull(targets); 686 Assert.isTrue(targets.length > 0); 687 Assert.isTrue(model.getTabStopSequence().size() > 0); 688 689 fModel= model; 690 fTargets= targets; 691 fCurrentTarget= targets[0]; 692 fIterator= new TabStopIterator(fModel.getTabStopSequence()); 693 fIterator.setCycling(!fModel.isNested()); 694 fModel.addLinkingListener(fLinkedListener); 695 696 fAssistant= new ContentAssistant2(); 697 fAssistant.addProposalListener(fProposalListener); 698 701 fCaretPosition.delete(); 702 } 703 704 707 public void enter() { 708 fIsActive= true; 709 connect(); 710 next(); 711 } 712 713 719 public void setExitPolicy(IExitPolicy policy) { 720 fExitPolicy= policy; 721 } 722 723 737 public void setExitPosition(LinkedModeUITarget target, int offset, int length, int sequence) throws BadLocationException { 738 if (fExitPosition != null) { 740 fExitPosition.getDocument().removePosition(fExitPosition); 741 fIterator.removePosition(fExitPosition); 742 fExitPosition= null; 743 } 744 745 IDocument doc= target.getViewer().getDocument(); 746 if (doc == null) 747 return; 748 749 fExitPosition= new LinkedPosition(doc, offset, length, sequence); 750 doc.addPosition(fExitPosition); if (sequence != LinkedPositionGroup.NO_STOP) 752 fIterator.addPosition(fExitPosition); 753 754 } 755 756 768 public void setExitPosition(ITextViewer viewer, int offset, int length, int sequence) throws BadLocationException { 769 setExitPosition(new EmptyTarget(viewer), offset, length, sequence); 770 } 771 772 779 public void setCyclingMode(Object mode) { 780 if (mode != CYCLE_ALWAYS && mode != CYCLE_NEVER && mode != CYCLE_WHEN_NO_PARENT) 781 throw new IllegalArgumentException (); 782 783 if (mode == CYCLE_ALWAYS || mode == CYCLE_WHEN_NO_PARENT && !fModel.isNested()) 784 fIterator.setCycling(true); 785 else 786 fIterator.setCycling(false); 787 } 788 789 void next() { 790 if (fIterator.hasNext(fFramePosition)) { 791 switchPosition(fIterator.next(fFramePosition), true, true); 792 return; 793 } 794 leave(ILinkedModeListener.UPDATE_CARET); 795 } 796 797 void previous() { 798 if (fIterator.hasPrevious(fFramePosition)) { 799 switchPosition(fIterator.previous(fFramePosition), true, true); 800 } else 801 leave(ILinkedModeListener.SELECT); 803 } 804 805 private void triggerContextInfo() { 806 ITextOperationTarget target= fCurrentTarget.getViewer().getTextOperationTarget(); 807 if (target != null) { 808 if (target.canDoOperation(ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION)) 809 target.doOperation(ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); 810 } 811 } 812 813 814 private void triggerContentAssist() { 815 if (fFramePosition instanceof ProposalPosition) { 816 ProposalPosition pp= (ProposalPosition) fFramePosition; 817 ICompletionProposal[] choices= pp.getChoices(); 818 if (choices != null && choices.length > 0) { 819 fAssistant.setCompletions(choices); 820 fAssistant.showPossibleCompletions(); 821 return; 822 } 823 } 824 825 fAssistant.setCompletions(new ICompletionProposal[0]); 826 fAssistant.hidePossibleCompletions(); 827 } 828 829 private void switchPosition(LinkedPosition pos, boolean select, boolean showProposals) { 830 Assert.isNotNull(pos); 831 if (pos.equals(fFramePosition)) 832 return; 833 834 if (fFramePosition != null && fCurrentTarget != null) 835 fPositionListener.linkingFocusLost(fFramePosition, fCurrentTarget); 836 837 endCompoundChange(); 839 840 redraw(); IDocument oldDoc= fFramePosition == null ? null : fFramePosition.getDocument(); 842 IDocument newDoc= pos.getDocument(); 843 844 switchViewer(oldDoc, newDoc, pos); 845 fFramePosition= pos; 846 847 if (select) 848 select(); 849 if (fFramePosition == fExitPosition && !fIterator.isCycling()) 850 leave(ILinkedModeListener.NONE); 851 else { 852 redraw(); ensureAnnotationModelInstalled(); 854 } 855 if (showProposals) 856 triggerContentAssist(); 857 if (fFramePosition != fExitPosition && fDoContextInfo) 858 triggerContextInfo(); 859 860 if (fFramePosition != null && fCurrentTarget != null) 861 fPositionListener.linkingFocusGained(fFramePosition, fCurrentTarget); 862 863 } 864 865 private void ensureAnnotationModelInstalled() { 866 LinkedPositionAnnotations lpa= fCurrentTarget.fAnnotationModel; 867 if (lpa != null) { 868 ITextViewer viewer= fCurrentTarget.getViewer(); 869 if (viewer instanceof ISourceViewer) { 870 ISourceViewer sv= (ISourceViewer) viewer; 871 IAnnotationModel model= sv.getAnnotationModel(); 872 if (model instanceof IAnnotationModelExtension) { 873 IAnnotationModelExtension ext= (IAnnotationModelExtension) model; 874 IAnnotationModel ourModel= ext.getAnnotationModel(getUniqueKey()); 875 if (ourModel == null) { 876 ext.addAnnotationModel(getUniqueKey(), lpa); 877 } 878 } 879 } 880 } 881 } 882 883 private void uninstallAnnotationModel(LinkedModeUITarget target) { 884 ITextViewer viewer= target.getViewer(); 885 if (viewer instanceof ISourceViewer) { 886 ISourceViewer sv= (ISourceViewer) viewer; 887 IAnnotationModel model= sv.getAnnotationModel(); 888 if (model instanceof IAnnotationModelExtension) { 889 IAnnotationModelExtension ext= (IAnnotationModelExtension) model; 890 ext.removeAnnotationModel(getUniqueKey()); 891 } 892 } 893 } 894 895 private void switchViewer(IDocument oldDoc, IDocument newDoc, LinkedPosition pos) { 896 if (oldDoc != newDoc) { 897 898 if (fCurrentTarget.fAnnotationModel != null) 900 fCurrentTarget.fAnnotationModel.switchToPosition(fModel, pos); 901 902 LinkedModeUITarget target= null; 903 for (int i= 0; i < fTargets.length; i++) { 904 if (fTargets[i].getViewer().getDocument() == newDoc) { 905 target= fTargets[i]; 906 break; 907 } 908 } 909 if (target != fCurrentTarget) { 910 disconnect(); 911 fCurrentTarget= target; 912 target.linkingFocusLost(fFramePosition, target); 913 connect(); 914 ensureAnnotationModelInstalled(); 915 if (fCurrentTarget != null) 916 fCurrentTarget.linkingFocusGained(pos, fCurrentTarget); 917 } 918 } 919 } 920 921 private void select() { 922 ITextViewer viewer= fCurrentTarget.getViewer(); 923 if (viewer instanceof ITextViewerExtension5) { 924 ITextViewerExtension5 extension5= (ITextViewerExtension5) viewer; 925 extension5.exposeModelRange(new Region(fFramePosition.offset, fFramePosition.length)); 926 } else if (!viewer.overlapsWithVisibleRegion(fFramePosition.offset, fFramePosition.length)) { 927 viewer.resetVisibleRegion(); 928 } 929 viewer.revealRange(fFramePosition.offset, fFramePosition.length); 930 viewer.setSelectedRange(fFramePosition.offset, fFramePosition.length); 931 } 932 933 private void redraw() { 934 if (fCurrentTarget.fAnnotationModel != null) 935 fCurrentTarget.fAnnotationModel.switchToPosition(fModel, fFramePosition); 936 } 937 938 private void connect() { 939 Assert.isNotNull(fCurrentTarget); 940 ITextViewer viewer= fCurrentTarget.getViewer(); 941 Assert.isNotNull(viewer); 942 fCurrentTarget.fWidget= viewer.getTextWidget(); 943 if (fCurrentTarget.fWidget == null) 944 leave(ILinkedModeListener.EXIT_ALL); 945 946 if (fCurrentTarget.fKeyListener == null) { 947 fCurrentTarget.fKeyListener= new KeyListener(); 948 ((ITextViewerExtension) viewer).prependVerifyKeyListener(fCurrentTarget.fKeyListener); 949 } else 950 fCurrentTarget.fKeyListener.setEnabled(true); 951 952 registerAutoEditVetoer(viewer); 953 954 ((IPostSelectionProvider) viewer).addPostSelectionChangedListener(fSelectionListener); 955 956 createAnnotationModel(); 957 958 showSelection(); 959 960 fCurrentTarget.fShell= fCurrentTarget.fWidget.getShell(); 961 if (fCurrentTarget.fShell == null) 962 leave(ILinkedModeListener.EXIT_ALL); 963 fCurrentTarget.fShell.addShellListener(fCloser); 964 965 fAssistant.install(viewer); 966 967 viewer.addTextInputListener(fCloser); 968 969 viewer.getDocument().addDocumentListener(fDocumentListener); 970 } 971 972 975 private void showSelection() { 976 final StyledText widget= fCurrentTarget.fWidget; 977 if (widget == null || widget.isDisposed()) 978 return; 979 980 widget.getDisplay().asyncExec(new Runnable () { 982 public void run() { 983 if (!widget.isDisposed()) 984 try { 985 widget.showSelection(); 986 } catch (IllegalArgumentException e) { 987 996 } 997 } 998 }); 999 } 1000 1001 1007 private void registerAutoEditVetoer(ITextViewer viewer) { 1008 try { 1009 String [] contentTypes= getContentTypes(viewer.getDocument()); 1010 if (viewer instanceof ITextViewerExtension2) { 1011 ITextViewerExtension2 vExtension= ((ITextViewerExtension2) viewer); 1012 for (int i= 0; i < contentTypes.length; i++) { 1013 vExtension.prependAutoEditStrategy(fAutoEditVetoer, contentTypes[i]); 1014 } 1015 } else { 1016 Assert.isTrue(false); 1017 } 1018 1019 } catch (BadPartitioningException e) { 1020 leave(ILinkedModeListener.EXIT_ALL); 1021 } 1022 } 1023 1024 private void unregisterAutoEditVetoer(ITextViewer viewer) { 1025 try { 1026 String [] contentTypes= getContentTypes(viewer.getDocument()); 1027 if (viewer instanceof ITextViewerExtension2) { 1028 ITextViewerExtension2 vExtension= ((ITextViewerExtension2) viewer); 1029 for (int i= 0; i < contentTypes.length; i++) { 1030 vExtension.removeAutoEditStrategy(fAutoEditVetoer, contentTypes[i]); 1031 } 1032 } else { 1033 Assert.isTrue(false); 1034 } 1035 } catch (BadPartitioningException e) { 1036 leave(ILinkedModeListener.EXIT_ALL); 1037 } 1038 } 1039 1040 1048 private String [] getContentTypes(IDocument document) throws BadPartitioningException { 1049 if (document instanceof IDocumentExtension3) { 1050 IDocumentExtension3 ext= (IDocumentExtension3) document; 1051 String [] partitionings= ext.getPartitionings(); 1052 Set contentTypes= new HashSet (20); 1053 for (int i= 0; i < partitionings.length; i++) { 1054 contentTypes.addAll(Arrays.asList(ext.getLegalContentTypes(partitionings[i]))); 1055 } 1056 contentTypes.add(IDocument.DEFAULT_CONTENT_TYPE); 1057 return (String []) contentTypes.toArray(new String [contentTypes.size()]); 1058 } 1059 return document.getLegalContentTypes(); 1060 } 1061 1062 private void createAnnotationModel() { 1063 if (fCurrentTarget.fAnnotationModel == null) { 1064 LinkedPositionAnnotations lpa= new LinkedPositionAnnotations(); 1065 if (fSimple) { 1066 lpa.markExitTarget(true); 1067 lpa.markFocus(false); 1068 lpa.markSlaves(false); 1069 lpa.markTargets(false); 1070 } 1071 lpa.setTargets(fIterator.getPositions()); 1072 lpa.setExitTarget(fExitPosition); 1073 lpa.connect(fCurrentTarget.getViewer().getDocument()); 1074 fCurrentTarget.fAnnotationModel= lpa; 1075 } 1076 } 1077 1078 private String getUniqueKey() { 1079 return "linked.annotationmodelkey."+toString(); } 1081 1082 private void disconnect() { 1083 Assert.isNotNull(fCurrentTarget); 1084 ITextViewer viewer= fCurrentTarget.getViewer(); 1085 Assert.isNotNull(viewer); 1086 1087 viewer.getDocument().removeDocumentListener(fDocumentListener); 1088 1089 fAssistant.uninstall(); 1090 fAssistant.removeProposalListener(fProposalListener); 1091 1092 fCurrentTarget.fWidget= null; 1093 1094 Shell shell= fCurrentTarget.fShell; 1095 fCurrentTarget.fShell= null; 1096 1097 if (shell != null && !shell.isDisposed()) 1098 shell.removeShellListener(fCloser); 1099 1100 uninstallAnnotationModel(fCurrentTarget); 1104 1105 unregisterAutoEditVetoer(viewer); 1106 1107 if (fCurrentTarget.fKeyListener != null) 1110 fCurrentTarget.fKeyListener.setEnabled(false); 1111 1112 ((IPostSelectionProvider) viewer).removePostSelectionChangedListener(fSelectionListener); 1113 1114 redraw(); 1115 } 1116 1117 void leave(final int flags) { 1118 if (!fIsActive) 1119 return; 1120 fIsActive= false; 1121 1122 endCompoundChange(); 1123 1124 Display display= null; 1125 if (fCurrentTarget.fWidget != null && !fCurrentTarget.fWidget.isDisposed()) 1126 display= fCurrentTarget.fWidget.getDisplay(); 1127 1128 if (fCurrentTarget.fAnnotationModel != null) 1129 fCurrentTarget.fAnnotationModel.removeAllAnnotations(); 1130 disconnect(); 1131 1132 for (int i= 0; i < fTargets.length; i++) { 1133 LinkedModeUITarget target= fTargets[i]; 1134 ITextViewer viewer= target.getViewer(); 1135 if (target.fKeyListener != null) { 1136 ((ITextViewerExtension) viewer).removeVerifyKeyListener(target.fKeyListener); 1137 target.fKeyListener= null; 1138 } 1139 1140 viewer.removeTextInputListener(fCloser); 1141 } 1142 1143 for (int i= 0; i < fTargets.length; i++) { 1144 1145 if (fTargets[i].fAnnotationModel != null) { 1146 fTargets[i].fAnnotationModel.removeAllAnnotations(); 1147 fTargets[i].fAnnotationModel.disconnect(fTargets[i].getViewer().getDocument()); 1148 fTargets[i].fAnnotationModel= null; 1149 } 1150 1151 uninstallAnnotationModel(fTargets[i]); 1152 } 1153 1154 1155 if ((flags & ILinkedModeListener.UPDATE_CARET) != 0 && fExitPosition != null && fFramePosition != fExitPosition && !fExitPosition.isDeleted()) 1156 switchPosition(fExitPosition, true, false); 1157 1158 final List docs= new ArrayList (); 1159 for (int i= 0; i < fTargets.length; i++) { 1160 IDocument doc= fTargets[i].getViewer().getDocument(); 1161 if (doc != null) 1162 docs.add(doc); 1163 } 1164 1165 fModel.stopForwarding(flags); 1166 1167 Runnable runnable= new Runnable () { 1168 public void run() { 1169 if (fExitPosition != null) 1170 fExitPosition.getDocument().removePosition(fExitPosition); 1171 1172 for (Iterator iter = docs.iterator(); iter.hasNext(); ) { 1173 IDocument doc= (IDocument) iter.next(); 1174 doc.removePositionUpdater(fPositionUpdater); 1175 boolean uninstallCat= false; 1176 String [] cats= doc.getPositionCategories(); 1177 for (int j= 0; j < cats.length; j++) { 1178 if (getCategory().equals(cats[j])) { 1179 uninstallCat= true; 1180 break; 1181 } 1182 } 1183 if (uninstallCat) 1184 try { 1185 doc.removePositionCategory(getCategory()); 1186 } catch (BadPositionCategoryException e) { 1187 } 1189 } 1190 fModel.exit(flags); 1191 } 1192 }; 1193 1194 if (display != null) 1198 display.asyncExec(runnable); 1199 else 1200 runnable.run(); 1201 } 1202 1203 private void endCompoundChange() { 1204 if (fHasOpenCompoundChange) { 1205 ITextViewerExtension extension= (ITextViewerExtension) fCurrentTarget.getViewer(); 1206 IRewriteTarget target= extension.getRewriteTarget(); 1207 target.endCompoundChange(); 1208 fHasOpenCompoundChange= false; 1209 } 1210 } 1211 1212 private void beginCompoundChange() { 1213 if (!fHasOpenCompoundChange) { 1214 ITextViewerExtension extension= (ITextViewerExtension) fCurrentTarget.getViewer(); 1215 IRewriteTarget target= extension.getRewriteTarget(); 1216 target.beginCompoundChange(); 1217 fHasOpenCompoundChange= true; 1218 } 1219 } 1220 1221 1226 public IRegion getSelectedRegion() { 1227 if (fFramePosition != null) 1228 return new Region(fFramePosition.getOffset(), fFramePosition.getLength()); 1229 if (fExitPosition != null) 1230 return new Region(fExitPosition.getOffset(), fExitPosition.getLength()); 1231 return null; 1232 } 1233 1234 private String getCategory() { 1235 return toString(); 1236 } 1237 1238 1246 public void setDoContextInfo(boolean doContextInfo) { 1247 fDoContextInfo= doContextInfo; 1248 } 1249 1250 1259 protected void setPositionListener(ILinkedModeUIFocusListener listener) { 1260 Assert.isNotNull(listener); 1261 fPositionListener= listener; 1262 } 1263 1264 1272 public void setSimpleMode(boolean simple) { 1273 fSimple= simple; 1274 } 1275 1276} 1277 | Popular Tags |