1 16 17 package org.eclipse.ant.internal.ui.editor; 18 19 import java.io.File ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.ResourceBundle ; 25 26 import org.eclipse.ant.internal.ui.AntUIPlugin; 27 import org.eclipse.ant.internal.ui.AntUtil; 28 import org.eclipse.ant.internal.ui.ExternalHyperlink; 29 import org.eclipse.ant.internal.ui.IAntUIHelpContextIds; 30 import org.eclipse.ant.internal.ui.IAntUIPreferenceConstants; 31 import org.eclipse.ant.internal.ui.editor.actions.FoldingActionGroup; 32 import org.eclipse.ant.internal.ui.editor.actions.OpenDeclarationAction; 33 import org.eclipse.ant.internal.ui.editor.actions.RenameInFileAction; 34 import org.eclipse.ant.internal.ui.editor.actions.RunToLineAdapter; 35 import org.eclipse.ant.internal.ui.editor.actions.ToggleLineBreakpointAction; 36 import org.eclipse.ant.internal.ui.editor.outline.AntEditorContentOutlinePage; 37 import org.eclipse.ant.internal.ui.editor.text.AntEditorDocumentProvider; 38 import org.eclipse.ant.internal.ui.editor.text.AntFoldingStructureProvider; 39 import org.eclipse.ant.internal.ui.editor.text.IReconcilingParticipant; 40 import org.eclipse.ant.internal.ui.editor.text.XMLTextHover; 41 import org.eclipse.ant.internal.ui.model.AntElementNode; 42 import org.eclipse.ant.internal.ui.model.AntModel; 43 import org.eclipse.ant.internal.ui.model.AntModelChangeEvent; 44 import org.eclipse.ant.internal.ui.model.AntModelCore; 45 import org.eclipse.ant.internal.ui.model.AntProjectNode; 46 import org.eclipse.ant.internal.ui.model.IAntModelListener; 47 import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants; 48 import org.eclipse.core.resources.IFile; 49 import org.eclipse.core.runtime.CoreException; 50 import org.eclipse.core.runtime.IProgressMonitor; 51 import org.eclipse.core.runtime.IStatus; 52 import org.eclipse.core.runtime.NullProgressMonitor; 53 import org.eclipse.core.runtime.Status; 54 import org.eclipse.core.runtime.jobs.Job; 55 import org.eclipse.debug.ui.actions.IRunToLineTarget; 56 import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; 57 import org.eclipse.jdt.ui.JavaUI; 58 import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds; 59 import org.eclipse.jface.action.IAction; 60 import org.eclipse.jface.action.IMenuManager; 61 import org.eclipse.jface.action.Separator; 62 import org.eclipse.jface.preference.IPreferenceStore; 63 import org.eclipse.jface.text.BadLocationException; 64 import org.eclipse.jface.text.DocumentEvent; 65 import org.eclipse.jface.text.IAutoEditStrategy; 66 import org.eclipse.jface.text.IDocument; 67 import org.eclipse.jface.text.IDocumentListener; 68 import org.eclipse.jface.text.IInformationControl; 69 import org.eclipse.jface.text.IInformationControlCreator; 70 import org.eclipse.jface.text.IRegion; 71 import org.eclipse.jface.text.ISelectionValidator; 72 import org.eclipse.jface.text.ISynchronizable; 73 import org.eclipse.jface.text.ITextInputListener; 74 import org.eclipse.jface.text.ITextSelection; 75 import org.eclipse.jface.text.ITextViewer; 76 import org.eclipse.jface.text.Position; 77 import org.eclipse.jface.text.link.LinkedModeModel; 78 import org.eclipse.jface.text.source.Annotation; 79 import org.eclipse.jface.text.source.IAnnotationModel; 80 import org.eclipse.jface.text.source.IAnnotationModelExtension; 81 import org.eclipse.jface.text.source.IOverviewRuler; 82 import org.eclipse.jface.text.source.ISourceViewer; 83 import org.eclipse.jface.text.source.IVerticalRuler; 84 import org.eclipse.jface.text.source.SourceViewerConfiguration; 85 import org.eclipse.jface.text.source.projection.IProjectionListener; 86 import org.eclipse.jface.text.source.projection.ProjectionSupport; 87 import org.eclipse.jface.text.source.projection.ProjectionViewer; 88 import org.eclipse.jface.util.PropertyChangeEvent; 89 import org.eclipse.jface.viewers.IPostSelectionProvider; 90 import org.eclipse.jface.viewers.ISelection; 91 import org.eclipse.jface.viewers.ISelectionChangedListener; 92 import org.eclipse.jface.viewers.ISelectionProvider; 93 import org.eclipse.jface.viewers.IStructuredSelection; 94 import org.eclipse.jface.viewers.SelectionChangedEvent; 95 import org.eclipse.swt.custom.StyledText; 96 import org.eclipse.swt.events.ShellAdapter; 97 import org.eclipse.swt.events.ShellEvent; 98 import org.eclipse.swt.graphics.Image; 99 import org.eclipse.swt.widgets.Composite; 100 import org.eclipse.swt.widgets.Shell; 101 import org.eclipse.ui.IEditorInput; 102 import org.eclipse.ui.IPageLayout; 103 import org.eclipse.ui.IPartService; 104 import org.eclipse.ui.IWorkbenchPage; 105 import org.eclipse.ui.IWorkbenchPart; 106 import org.eclipse.ui.IWorkbenchWindow; 107 import org.eclipse.ui.PartInitException; 108 import org.eclipse.ui.editors.text.TextEditor; 109 import org.eclipse.ui.ide.IDE; 110 import org.eclipse.ui.part.IShowInTargetList; 111 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; 112 import org.eclipse.ui.texteditor.ContentAssistAction; 113 import org.eclipse.ui.texteditor.IDocumentProvider; 114 import org.eclipse.ui.texteditor.IEditorStatusLine; 115 import org.eclipse.ui.texteditor.ITextEditorActionConstants; 116 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; 117 import org.eclipse.ui.texteditor.TextOperationAction; 118 import org.eclipse.ui.views.contentoutline.ContentOutline; 119 import org.eclipse.ui.views.contentoutline.IContentOutlinePage; 120 121 124 public class AntEditor extends TextEditor implements IReconcilingParticipant, IProjectionListener { 125 130 private class EditorSelectionChangedListener implements ISelectionChangedListener { 131 132 140 public void install(ISelectionProvider selectionProvider) { 141 if (selectionProvider == null || getAntModel() == null) { 142 return; 143 } 144 145 if (selectionProvider instanceof IPostSelectionProvider) { 146 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider; 147 provider.addPostSelectionChangedListener(this); 148 } else { 149 selectionProvider.addSelectionChangedListener(this); 150 } 151 } 152 153 158 public void uninstall(ISelectionProvider selectionProvider) { 159 if (selectionProvider == null || getAntModel() == null) { 160 return; 161 } 162 163 if (selectionProvider instanceof IPostSelectionProvider) { 164 IPostSelectionProvider provider= (IPostSelectionProvider) selectionProvider; 165 provider.removePostSelectionChangedListener(this); 166 } else { 167 selectionProvider.removeSelectionChangedListener(this); 168 } 169 } 170 171 174 public void selectionChanged(SelectionChangedEvent event) { 175 AntModel model= getAntModel(); 176 ISelection selection= event.getSelection(); 177 AntElementNode node= null; 178 if (selection instanceof ITextSelection) { 179 ITextSelection textSelection= (ITextSelection)selection; 180 int offset= textSelection.getOffset(); 181 node= model.getNode(offset, false); 182 updateOccurrenceAnnotations(textSelection, model); 183 } 184 185 if (AntUIPlugin.getDefault().getPreferenceStore().getBoolean(IAntUIPreferenceConstants.OUTLINE_LINK_WITH_EDITOR)) { 186 synchronizeOutlinePage(node, true); 187 } 188 setSelection(node, false); 189 } 190 } 191 192 class StatusLineSourceViewer extends ProjectionViewer{ 193 194 public StatusLineSourceViewer(Composite composite, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, int styles) { 195 super(composite, verticalRuler, overviewRuler, isOverviewRulerVisible(), styles); 196 } 197 198 201 public void doOperation(int operation) { 202 if (getTextWidget() == null || !redraws()) { 203 return; 204 } 205 206 switch (operation) { 207 case CONTENTASSIST_PROPOSALS: 208 String msg= fContentAssistant.showPossibleCompletions(); 209 setStatusLineErrorMessage(msg); 210 return; 211 } 212 213 super.doOperation(operation); 214 } 215 } 216 217 218 223 class OccurrencesFinderJob extends Job { 224 225 private IDocument fDocument; 226 private ISelection fSelection; 227 private ISelectionValidator fPostSelectionValidator; 228 private boolean fCanceled= false; 229 private IProgressMonitor fProgressMonitor; 230 private List fPositions; 231 232 public OccurrencesFinderJob(IDocument document, List positions, ISelection selection) { 233 super("Occurrences Marker"); fDocument= document; 235 fSelection= selection; 236 fPositions= positions; 237 238 if (getSelectionProvider() instanceof ISelectionValidator) 239 fPostSelectionValidator= (ISelectionValidator)getSelectionProvider(); 240 } 241 242 void doCancel() { 244 fCanceled= true; 245 cancel(); 246 } 247 248 private boolean isCanceled() { 249 return fCanceled || fProgressMonitor.isCanceled() 250 || fPostSelectionValidator != null && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection) 251 || LinkedModeModel.hasInstalledModel(fDocument); 252 } 253 254 257 public IStatus run(IProgressMonitor progressMonitor) { 258 259 fProgressMonitor= progressMonitor; 260 261 if (isCanceled()) 262 return Status.CANCEL_STATUS; 263 264 ITextViewer textViewer= getViewer(); 265 if (textViewer == null) 266 return Status.CANCEL_STATUS; 267 268 IDocument document= textViewer.getDocument(); 269 if (document == null) 270 return Status.CANCEL_STATUS; 271 272 IDocumentProvider documentProvider= getDocumentProvider(); 273 if (documentProvider == null) 274 return Status.CANCEL_STATUS; 275 276 IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); 277 if (annotationModel == null) 278 return Status.CANCEL_STATUS; 279 280 int length= fPositions.size(); 282 Map annotationMap= new HashMap (length); 283 for (int i= 0; i < length; i++) { 284 285 if (isCanceled()) 286 return Status.CANCEL_STATUS; 287 288 String message; 289 Position position= (Position) fPositions.get(i); 290 291 try { 293 message= document.get(position.offset, position.length); 294 } catch (BadLocationException ex) { 295 continue; 297 } 298 annotationMap.put( 299 new Annotation("org.eclipse.jdt.ui.occurrences", false, message), position); 301 } 302 303 if (isCanceled()) { 304 return Status.CANCEL_STATUS; 305 } 306 307 Object lock= getLockObject(document); 308 if (lock == null) { 309 updateAnnotations(annotationModel, annotationMap); 310 } else { 311 synchronized (lock) { 312 updateAnnotations(annotationModel, annotationMap); 313 } 314 } 315 316 return Status.OK_STATUS; 317 } 318 319 private void updateAnnotations(IAnnotationModel annotationModel, Map annotationMap) { 320 if (annotationModel instanceof IAnnotationModelExtension) { 321 ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap); 322 } else { 323 removeOccurrenceAnnotations(); 324 Iterator iter= annotationMap.entrySet().iterator(); 325 while (iter.hasNext()) { 326 Map.Entry mapEntry= (Map.Entry )iter.next(); 327 annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue()); 328 } 329 } 330 fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]); 331 } 332 } 333 334 339 class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener { 340 341 public void install() { 342 ISourceViewer sourceViewer= getSourceViewer(); 343 if (sourceViewer == null) 344 return; 345 346 StyledText text= sourceViewer.getTextWidget(); 347 if (text == null || text.isDisposed()) 348 return; 349 350 sourceViewer.addTextInputListener(this); 351 352 IDocument document= sourceViewer.getDocument(); 353 if (document != null) 354 document.addDocumentListener(this); 355 } 356 357 public void uninstall() { 358 ISourceViewer sourceViewer= getSourceViewer(); 359 if (sourceViewer != null) 360 sourceViewer.removeTextInputListener(this); 361 362 IDocumentProvider documentProvider= getDocumentProvider(); 363 if (documentProvider != null) { 364 IDocument document= documentProvider.getDocument(getEditorInput()); 365 if (document != null) 366 document.removeDocumentListener(this); 367 } 368 } 369 370 371 374 public void documentAboutToBeChanged(DocumentEvent event) { 375 if (fOccurrencesFinderJob != null) 376 fOccurrencesFinderJob.doCancel(); 377 } 378 379 382 public void documentChanged(DocumentEvent event) { 383 } 384 385 388 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 389 if (oldInput == null) 390 return; 391 392 oldInput.removeDocumentListener(this); 393 } 394 395 398 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 399 if (newInput == null) 400 return; 401 newInput.addDocumentListener(this); 402 } 403 } 404 405 409 private class ActivationListener extends ShellAdapter { 410 413 public void shellActivated(ShellEvent e) { 414 if (fMarkOccurrenceAnnotations && isActivePart()) { 415 ISelection selection= getSelectionProvider().getSelection(); 416 if (selection instanceof ITextSelection) { 417 fForcedMarkOccurrencesSelection= (ITextSelection) selection; 418 updateOccurrenceAnnotations(fForcedMarkOccurrencesSelection, getAntModel()); 419 } 420 } 421 } 422 423 426 public void shellDeactivated(ShellEvent e) { 427 if (fMarkOccurrenceAnnotations && isActivePart()) 428 removeOccurrenceAnnotations(); 429 } 430 } 431 432 435 protected ISelectionChangedListener fSelectionChangedListener = new ISelectionChangedListener(){ 436 public void selectionChanged(SelectionChangedEvent event) { 437 fSelectionSetFromOutline= false; 438 doSelectionChanged(event); 439 fSelectionSetFromOutline= true; 440 } 441 }; 442 443 private IAntModelListener fAntModelListener= new IAntModelListener() { 444 447 public void antModelChanged(AntModelChangeEvent event) { 448 AntModel model= getAntModel(); 449 if (event.getModel() == model) { 450 if (event.isPreferenceChange()) { 451 updateEditorImage(model); 452 } 453 if (fFoldingStructureProvider != null) { 454 fFoldingStructureProvider.updateFoldingRegions(model); 455 } 456 } 457 } 458 }; 459 460 463 protected AntEditorContentOutlinePage fOutlinePage; 464 465 466 private boolean fInitialReconcile= true; 467 468 473 private EditorSelectionChangedListener fEditorSelectionChangedListener; 474 475 private ProjectionSupport fProjectionSupport; 476 477 private AntFoldingStructureProvider fFoldingStructureProvider; 478 479 private boolean fSelectionSetFromOutline= false; 480 481 private FoldingActionGroup fFoldingGroup; 482 483 487 private Annotation[] fOccurrenceAnnotations= null; 488 489 private OccurrencesFinderJob fOccurrencesFinderJob; 490 private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler; 491 492 private ITextSelection fForcedMarkOccurrencesSelection; 493 497 private ActivationListener fActivationListener= new ActivationListener(); 498 499 private boolean fMarkOccurrenceAnnotations; 500 private boolean fStickyOccurrenceAnnotations; 501 502 private AntModel fAntModel; 503 504 public AntEditor() { 505 super(); 506 setSourceViewerConfiguration(new AntEditorSourceViewerConfiguration(this)); 507 setDocumentProvider(AntUIPlugin.getDefault().getDocumentProvider()); 508 AntModelCore.getDefault().addAntModelListener(fAntModelListener); 509 510 if (isFoldingEnabled()) { 511 fFoldingStructureProvider= new AntFoldingStructureProvider(this); 512 } 513 } 514 515 516 519 protected void createActions() { 520 super.createActions(); 521 522 ResourceBundle bundle = ResourceBundle.getBundle("org.eclipse.ant.internal.ui.editor.AntEditorMessages"); IAction action = new ContentAssistAction(bundle, "ContentAssistProposal.", this); 525 action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); 527 setAction("ContentAssistProposal", action); 529 action = new TextOperationAction(bundle, "ContentFormat.", this, ISourceViewer.FORMAT); action.setActionDefinitionId(IJavaEditorActionDefinitionIds.FORMAT); 531 setAction("ContentFormat", action); 533 action = new OpenDeclarationAction(this); 534 setAction("OpenDeclaration", action); 536 fFoldingGroup= new FoldingActionGroup(this, getViewer()); 537 538 action= new RenameInFileAction(this); 539 action.setActionDefinitionId("org.eclipse.ant.ui.renameInFile"); setAction("renameInFile", action); } 542 543 548 protected void initializeEditor() { 549 super.initializeEditor(); 550 setPreferenceStore(AntUIPlugin.getDefault().getCombinedPreferenceStore()); 551 setCompatibilityMode(false); 552 setHelpContextId(IAntUIHelpContextIds.ANT_EDITOR); 553 setRulerContextMenuId("org.eclipse.ant.internal.ui.editor.AntEditor.RulerContext"); setEditorContextMenuId("org.eclipse.ant.internal.ui.editor.AntEditor"); fMarkOccurrenceAnnotations= getPreferenceStore().getBoolean(AntEditorPreferenceConstants.EDITOR_MARK_OCCURRENCES); 556 fStickyOccurrenceAnnotations= getPreferenceStore().getBoolean(AntEditorPreferenceConstants.EDITOR_STICKY_OCCURRENCES); 557 } 558 559 562 public Object getAdapter(Class key) { 563 if (key.equals(IContentOutlinePage.class)) { 564 return getOutlinePage(); 565 } 566 567 if (fProjectionSupport != null) { 568 Object adapter= fProjectionSupport.getAdapter(getSourceViewer(), key); 569 if (adapter != null) { 570 return adapter; 571 } 572 } 573 574 if (key == IShowInTargetList.class) { 575 return new IShowInTargetList() { 576 public String [] getShowInTargetIds() { 577 return new String [] { JavaUI.ID_PACKAGES, IPageLayout.ID_RES_NAV }; 578 } 579 }; 580 } 581 582 if (key == IToggleBreakpointsTarget.class) { 583 return new ToggleLineBreakpointAction(); 584 } 585 586 if (key == IRunToLineTarget.class) { 587 return new RunToLineAdapter(); 588 } 589 590 return super.getAdapter(key); 591 } 592 593 private AntEditorContentOutlinePage getOutlinePage() { 594 if (fOutlinePage == null) { 595 fOutlinePage= new AntEditorContentOutlinePage(AntModelCore.getDefault(), this); 596 fOutlinePage.addPostSelectionChangedListener(fSelectionChangedListener); 597 setOutlinePageInput(); 598 } 599 return fOutlinePage; 600 } 601 602 private void doSelectionChanged(SelectionChangedEvent selectionChangedEvent) { 603 IStructuredSelection selection= (IStructuredSelection)selectionChangedEvent.getSelection(); 604 605 if (!isActivePart() && AntUIPlugin.getActivePage() != null) { 606 AntUIPlugin.getActivePage().bringToTop(this); 607 } 608 609 AntElementNode selectedXmlElement = (AntElementNode)selection.getFirstElement(); 610 if(selectedXmlElement != null) { 611 setSelection(selectedXmlElement, !isActivePart()); 612 } 613 } 614 615 private boolean isActivePart() { 616 IWorkbenchPart part= getActivePart(); 617 return part != null && part.equals(this); 618 } 619 620 public void setSelection(AntElementNode reference, boolean moveCursor) { 621 if (fSelectionSetFromOutline) { 622 fSelectionSetFromOutline= false; 624 return; 625 } 626 if (reference == null) { 627 if (moveCursor) { 628 resetHighlightRange(); 629 markInNavigationHistory(); 630 } 631 return; 632 } 633 634 if (moveCursor) { 635 markInNavigationHistory(); 636 } 637 638 while (reference.getImportNode() != null) { 639 reference= reference.getImportNode(); 640 } 641 if (reference.isExternal()) { 642 return; 643 } 644 645 ISourceViewer sourceViewer= getSourceViewer(); 646 if (sourceViewer == null) { 647 return; 648 } 649 StyledText textWidget= sourceViewer.getTextWidget(); 650 if (textWidget == null) { 651 return; 652 } 653 654 try { 655 int offset= reference.getOffset(); 656 if (offset < 0) { 657 return; 658 } 659 int length= reference.getSelectionLength(); 660 int highLightLength= reference.getLength(); 661 662 textWidget.setRedraw(false); 663 664 if (highLightLength > 0) { 665 setHighlightRange(offset, highLightLength, moveCursor); 666 } 667 668 if (!moveCursor) { 669 return; 670 } 671 672 if (offset > -1 && length > 0) { 673 sourceViewer.revealRange(offset, length); 674 sourceViewer.setSelectedRange(offset, length); 676 markInNavigationHistory(); 677 } 678 } catch (IllegalArgumentException x) { 679 AntUIPlugin.log(x); 680 } finally { 681 textWidget.setRedraw(true); 682 } 683 } 684 685 688 protected boolean affectsTextPresentation(PropertyChangeEvent event) { 689 return ((AntEditorSourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event); 690 } 691 692 695 protected void handlePreferenceStoreChanged(PropertyChangeEvent event) { 696 String property= event.getProperty(); 697 698 if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) { 699 Object value= event.getNewValue(); 700 StatusLineSourceViewer viewer= (StatusLineSourceViewer) getSourceViewer(); 701 int newValue= -1; 702 if (value instanceof Integer ) { 703 newValue=((Integer ) value).intValue(); 704 } else if (value instanceof String ) { 705 newValue= Integer.parseInt((String ) value); 706 } 707 if (newValue != -1) { 708 viewer.getTextWidget().setTabs(newValue); 709 } 710 return; 711 } 712 713 if (AntEditorPreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) { 714 boolean newBooleanValue= Boolean.valueOf(event.getNewValue().toString()).booleanValue(); 715 if (newBooleanValue != fMarkOccurrenceAnnotations) { 716 fMarkOccurrenceAnnotations= newBooleanValue; 717 if (fMarkOccurrenceAnnotations) { 718 installOccurrencesFinder(); 719 } else { 720 uninstallOccurrencesFinder(); 721 } 722 } 723 return; 724 } 725 if (AntEditorPreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) { 726 boolean newBooleanValue= Boolean.valueOf(event.getNewValue().toString()).booleanValue(); 727 fStickyOccurrenceAnnotations= newBooleanValue; 728 return; 729 } 730 731 AntEditorSourceViewerConfiguration sourceViewerConfiguration= (AntEditorSourceViewerConfiguration)getSourceViewerConfiguration(); 732 if (sourceViewerConfiguration != null) { 733 if (affectsTextPresentation(event)) { 734 sourceViewerConfiguration.adaptToPreferenceChange(event); 735 } 736 737 sourceViewerConfiguration.changeConfiguration(event); 738 } 739 super.handlePreferenceStoreChanged(event); 740 } 741 742 745 protected void doSetInput(IEditorInput input) throws CoreException { 746 fAntModel= null; 747 super.doSetInput(input); 748 setOutlinePageInput(); 749 if (fFoldingStructureProvider != null) { 750 fFoldingStructureProvider.setDocument(getDocumentProvider().getDocument(input)); 751 } 752 } 753 754 private void setOutlinePageInput() { 755 if (fOutlinePage != null) { 756 fOutlinePage.setPageInput(getAntModel()); 757 } 758 } 759 760 764 public AntModel getAntModel() { 765 if (fAntModel == null) { 766 IDocumentProvider provider= getDocumentProvider(); 767 if (provider instanceof AntEditorDocumentProvider) { 768 AntEditorDocumentProvider documentProvider= (AntEditorDocumentProvider) provider; 769 fAntModel= documentProvider.getAntModel(getEditorInput()); 770 } 771 } 772 return fAntModel; 773 } 774 775 778 protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { 779 fOverviewRuler= createOverviewRuler(getSharedColors()); 780 ISourceViewer viewer= new StatusLineSourceViewer(parent, ruler, getOverviewRuler(), styles); 781 getSourceViewerDecorationSupport(viewer); 783 return viewer; 784 } 785 786 790 protected void setStatusLineErrorMessage(String msg) { 791 IEditorStatusLine statusLine= (IEditorStatusLine) getAdapter(IEditorStatusLine.class); 792 if (statusLine != null) 793 statusLine.setMessage(true, msg, null); 794 } 795 796 public void openReferenceElement() { 797 ISelection selection= getSelectionProvider().getSelection(); 798 Object target= null; 799 if (selection instanceof ITextSelection) { 800 ITextSelection textSelection= (ITextSelection)selection; 801 ISourceViewer viewer= getSourceViewer(); 802 int textOffset= textSelection.getOffset(); 803 IRegion region= XMLTextHover.getRegion(viewer, textOffset); 804 target= findTarget(region); 805 } 806 807 openTarget(target); 808 } 809 810 protected void openTarget(Object node) { 811 String errorMessage= null; 812 if (node instanceof AntElementNode) { 813 errorMessage= openNode((AntElementNode) node); 814 if (errorMessage == null) { 815 return; 816 } 817 } else if (node instanceof String ){ 818 errorMessage= openInEditor((String ) node, getAntModel().getEditedFile()); 819 if (errorMessage == null) { 820 return; 821 } 822 } 823 if (errorMessage == null || errorMessage.length() == 0) { 824 errorMessage= AntEditorMessages.getString("AntEditor.3"); } 826 setStatusLineErrorMessage(errorMessage); 827 getSite().getShell().getDisplay().beep(); 828 } 829 830 834 public Object findTarget(IRegion region) { 835 ISourceViewer viewer = getSourceViewer(); 836 AntElementNode node= null; 837 838 if (region != null) { 839 IDocument document= viewer.getDocument(); 840 String text= null; 841 try { 842 text= document.get(region.getOffset(), region.getLength()); 843 } catch (BadLocationException e) { 844 } 845 if (text != null && text.length() > 0) { 846 AntModel model= getAntModel(); 847 if (model == null) { 848 return null; 849 } 850 node= model.getReferenceNode(text); 851 if (node == null) { 852 node= model.getTargetNode(text); 853 if (node == null) { 854 node= model.getPropertyNode(text); 855 if (node == null) { 856 String path= model.getPath(text, region.getOffset()); 857 if (path != null) { 858 return path; 859 } 860 861 node= model.getDefininingTaskNode(text); 862 if (node == null) { 863 node= model.getMacroDefAttributeNode(text); 864 } 865 } 866 } 867 } 868 } 869 } 870 return node; 871 } 872 873 874 private String openNode(AntElementNode node) { 875 String errorMessage= null; 876 if (node.isExternal()) { 877 String path= node.getFilePath(); 878 errorMessage= openInEditor(path, null); 879 } else { 880 setSelection(node, true); 881 } 882 return errorMessage; 883 } 884 885 private String openInEditor(String path, File buildFile) { 886 File buildFileParent= null; 887 if (buildFile != null) { 888 buildFileParent= buildFile.getParentFile(); 889 } 890 IFile file= AntUtil.getFileForLocation(path, buildFileParent); 891 if (file != null && file.exists()) { 892 try { 893 IWorkbenchPage p= getEditorSite().getPage(); 894 if (p != null) { 895 IDE.openEditor(p, file, isActivePart()); 896 } 897 return null; 898 } catch (PartInitException e) { 899 return e.getLocalizedMessage(); 900 } 901 } 902 File externalFile= new File (path); 903 if (externalFile.exists()) { 904 new ExternalHyperlink(externalFile, -1).linkActivated(); 905 return null; 906 } 907 908 return ""; } 910 911 914 public void editorContextMenuAboutToShow(IMenuManager menu) { 915 super.editorContextMenuAboutToShow(menu); 916 917 if (getAntModel() != null) { 918 IAction action= getAction("OpenDeclaration"); if (action != null) { 920 String openGroup = "group.open"; menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(openGroup)); 922 menu.appendToGroup(openGroup, action); 923 } 924 925 action= getAction("renameInFile"); String editGroup = "group.edit"; menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, new Separator(editGroup)); 928 menu.appendToGroup(editGroup, action); 929 930 action= getAction("ContentFormat"); menu.appendToGroup(editGroup, action); 932 } 933 } 934 935 938 public void createPartControl(Composite parent) { 939 super.createPartControl(parent); 940 941 ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer(); 942 createFoldingSupport(projectionViewer); 943 if (isFoldingEnabled()) { 944 projectionViewer.doOperation(ProjectionViewer.TOGGLE); 945 } 946 947 if (fMarkOccurrenceAnnotations) { 948 installOccurrencesFinder(); 949 } 950 getEditorSite().getShell().addShellListener(fActivationListener); 951 952 fEditorSelectionChangedListener= new EditorSelectionChangedListener(); 953 fEditorSelectionChangedListener.install(getSelectionProvider()); 954 } 955 956 private void createFoldingSupport(ProjectionViewer projectionViewer) { 957 fProjectionSupport= new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors()); 958 fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() { 959 public IInformationControl createInformationControl(Shell shell) { 960 return new AntSourceViewerInformationControl(shell); 961 } 962 }); 963 fProjectionSupport.install(); 964 ((ProjectionViewer)getViewer()).addProjectionListener(this); 965 966 } 967 968 969 private boolean isFoldingEnabled() { 970 IPreferenceStore store= getPreferenceStore(); 971 return store.getBoolean(AntEditorPreferenceConstants.EDITOR_FOLDING_ENABLED); 972 } 973 974 978 protected boolean isTabsToSpacesConversionEnabled() { 979 return super.isTabsToSpacesConversionEnabled(); } 981 982 985 public void dispose() { 986 if (fEditorSelectionChangedListener != null) { 987 fEditorSelectionChangedListener.uninstall(getSelectionProvider()); 988 fEditorSelectionChangedListener= null; 989 } 990 991 ((ProjectionViewer)getViewer()).removeProjectionListener(this); 992 if (fProjectionSupport != null) { 993 fProjectionSupport.dispose(); 994 fProjectionSupport= null; 995 } 996 997 uninstallOccurrencesFinder(); 998 999 if (fActivationListener != null) { 1000 Shell shell= getEditorSite().getShell(); 1001 if (shell != null && !shell.isDisposed()) { 1002 shell.removeShellListener(fActivationListener); 1003 } 1004 fActivationListener= null; 1005 } 1006 1007 AntModelCore.getDefault().removeAntModelListener(fAntModelListener); 1008 fAntModel= null; 1009 super.dispose(); 1010 } 1011 1012 1015 public void doSave(IProgressMonitor monitor) { 1016 super.doSave(monitor); 1017 AntModel model= getAntModel(); 1018 model.updateMarkers(); 1019 updateEditorImage(model); 1020 } 1021 1022 private void updateEditorImage(AntModel model) { 1023 Image titleImage= getTitleImage(); 1024 if (titleImage == null) { 1025 return; 1026 } 1027 AntProjectNode node= model.getProjectNode(); 1028 if (node != null) { 1029 postImageChange(node); 1030 } 1031 } 1032 1033 private void updateForInitialReconcile() { 1034 IDocumentProvider provider= getDocumentProvider(); 1035 if (provider == null) { return; 1037 } 1038 if (getAntModel() == null) { 1039 return; 1040 } 1041 IDocument doc= provider.getDocument(getEditorInput()); 1042 if (doc == null) { 1043 return; } 1045 Object lock= getLockObject(doc); 1046 if (lock == null) { 1049 updateModelForInitialReconcile(); 1050 } else { 1051 synchronized (lock) { 1052 updateModelForInitialReconcile(); 1053 } 1054 } 1055 } 1056 1057 private void updateModelForInitialReconcile() { 1058 AntModel model= getAntModel(); 1059 if (model == null) { 1060 return; 1061 } 1062 1063 fInitialReconcile= false; 1064 updateEditorImage(model); 1065 model.updateForInitialReconcile(); 1066 } 1067 1068 private Object getLockObject(IDocument doc) { 1069 Object lock= null; 1070 if (doc instanceof ISynchronizable) { 1071 lock= ((ISynchronizable) doc).getLockObject(); 1072 } else { 1073 lock= getAntModel(); 1074 } 1075 return lock; 1076 } 1077 1078 private void postImageChange(final AntElementNode node) { 1079 Shell shell= getSite().getShell(); 1080 if (shell != null && !shell.isDisposed()) { 1081 shell.getDisplay().asyncExec(new Runnable () { 1082 public void run() { 1083 if (getSite().getShell() == null || getSite().getShell().isDisposed()) { 1084 return; 1085 } 1086 Image titleImage= getTitleImage(); 1087 Image newImage= node.getImage(); 1088 if (titleImage != newImage) { 1089 setTitleImage(newImage); 1090 } 1091 } 1092 }); 1093 } 1094 } 1095 1096 public void synchronizeOutlinePage(boolean checkIfOutlinePageActive) { 1097 if (getSelectionProvider() == null) { 1098 return; 1099 } 1100 AntElementNode node= getNode(); 1101 synchronizeOutlinePage(node, checkIfOutlinePageActive); 1102 1103 } 1104 1105 protected void synchronize(boolean checkIfOutlinePageActive) { 1106 if (getSelectionProvider() == null) { 1107 return; 1108 } 1109 AntElementNode node= getNode(); 1110 if (AntUIPlugin.getDefault().getPreferenceStore().getBoolean(IAntUIPreferenceConstants.OUTLINE_LINK_WITH_EDITOR)) { 1111 synchronizeOutlinePage(node, checkIfOutlinePageActive); 1112 } 1113 setSelection(node, false); 1114 1115 } 1116 1117 private AntElementNode getNode() { 1118 AntModel model= getAntModel(); 1119 if (model == null) { 1120 return null; 1121 } 1122 AntElementNode node= null; 1123 ISelection selection= getSelectionProvider().getSelection(); 1124 if (selection instanceof ITextSelection) { 1125 ITextSelection textSelection= (ITextSelection)selection; 1126 int offset= textSelection.getOffset(); 1127 node= model.getNode(offset, false); 1128 } 1129 return node; 1130 } 1131 1132 protected void synchronizeOutlinePage(AntElementNode node, boolean checkIfOutlinePageActive) { 1133 if (fOutlinePage != null && !(checkIfOutlinePageActive && isAntOutlinePageActive())) { 1134 fOutlinePage.removePostSelectionChangedListener(fSelectionChangedListener); 1135 fOutlinePage.select(node); 1136 fOutlinePage.addPostSelectionChangedListener(fSelectionChangedListener); 1137 } 1138 } 1139 1140 1143 public void reconciled() { 1144 if (fInitialReconcile) { 1145 updateForInitialReconcile(); 1146 } 1147 1148 SourceViewerConfiguration config= getSourceViewerConfiguration(); 1149 if (config == null) { 1150 return; } 1152 IAutoEditStrategy[] strategies= config.getAutoEditStrategies(getViewer(), null); 1153 for (int i = 0; i < strategies.length; i++) { 1154 IAutoEditStrategy strategy = strategies[i]; 1155 if (strategy instanceof AntAutoEditStrategy) { 1156 ((AntAutoEditStrategy)strategy).reconciled(); 1157 } 1158 } 1159 1160 Shell shell= getSite().getShell(); 1161 if (shell != null && !shell.isDisposed()) { 1162 shell.getDisplay().asyncExec(new Runnable () { 1163 public void run() { 1164 if (getSite().getShell() == null || getSite().getShell().isDisposed()) { 1165 return; 1166 } 1167 synchronize(true); 1168 } 1169 }); 1170 } 1171 } 1172 1173 private boolean isAntOutlinePageActive() { 1174 IWorkbenchPart part= getActivePart(); 1175 return part instanceof ContentOutline && ((ContentOutline)part).getCurrentPage() == fOutlinePage; 1176 } 1177 1178 private IWorkbenchPart getActivePart() { 1179 IWorkbenchWindow window= getSite().getWorkbenchWindow(); 1180 IPartService service= window.getPartService(); 1181 return service.getActivePart(); 1182 } 1183 1184 1187 protected void doSetSelection(ISelection selection) { 1188 super.doSetSelection(selection); 1189 synchronizeOutlinePage(true); 1190 } 1191 1192 1196 public ISourceViewer getViewer() { 1197 return getSourceViewer(); 1198 } 1199 1200 protected FoldingActionGroup getFoldingActionGroup() { 1201 return fFoldingGroup; 1202 } 1203 1204 1207 public void projectionEnabled() { 1208 fFoldingStructureProvider= new AntFoldingStructureProvider(this); 1209 fFoldingStructureProvider.setDocument(getDocumentProvider().getDocument(getEditorInput())); 1210 fFoldingStructureProvider.updateFoldingRegions(getAntModel()); 1211 } 1212 1213 1216 public void projectionDisabled() { 1217 fFoldingStructureProvider= null; 1218 } 1219 1220 1223 protected void initializeKeyBindingScopes() { 1224 setKeyBindingScopes(new String [] { "org.eclipse.ant.ui.AntEditorScope" }); } 1226 1227 protected IPreferenceStore getEditorPreferenceStore() { 1228 return getPreferenceStore(); 1229 } 1230 1231 1235 protected String [] collectContextMenuPreferencePages() { 1236 String [] ids= super.collectContextMenuPreferencePages(); 1237 String [] more= new String [ids.length + 6]; 1238 more[0]= "org.eclipse.ant.ui.AntEditorPreferencePage"; more[1]= "org.eclipse.ant.ui.AntCodeFormatterPreferencePage"; more[2]= "org.eclipse.ant.ui.AntCodeAssistPreferencePage"; more[3]= "org.eclipse.ant.ui.TemplatesPreferencePage"; more[4]= "org.eclipse.ant.ui.AntPreferencePage"; more[5]= "org.eclipse.ant.ui.AntRuntimePreferencePage"; System.arraycopy(ids, 0, more, 6, ids.length); 1245 return more; 1246 } 1247 1248 1256 protected void updateOccurrenceAnnotations(ITextSelection selection, AntModel antModel) { 1257 1258 if (fOccurrencesFinderJob != null) 1259 fOccurrencesFinderJob.cancel(); 1260 1261 if (!fMarkOccurrenceAnnotations) { 1262 return; 1263 } 1264 1265 if (selection == null || antModel == null) { 1266 return; 1267 } 1268 1269 IDocument document= getSourceViewer().getDocument(); 1270 if (document == null) { 1271 return; 1272 } 1273 1274 List positions= null; 1275 1276 OccurrencesFinder finder= new OccurrencesFinder(this, antModel, document, selection.getOffset()); 1277 positions= finder.perform(); 1278 1279 if (positions == null || positions.size() == 0) { 1280 if (!fStickyOccurrenceAnnotations) { 1281 removeOccurrenceAnnotations(); 1282 } 1283 return; 1284 } 1285 1286 fOccurrencesFinderJob= new OccurrencesFinderJob(document, positions, selection); 1287 fOccurrencesFinderJob.run(new NullProgressMonitor()); 1288 } 1289 1290 private void removeOccurrenceAnnotations() { 1291 IDocumentProvider documentProvider= getDocumentProvider(); 1292 if (documentProvider == null) { 1293 return; 1294 } 1295 1296 IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput()); 1297 if (annotationModel == null || fOccurrenceAnnotations == null) { 1298 return; 1299 } 1300 1301 IDocument document= documentProvider.getDocument(getEditorInput()); 1302 Object lock= getLockObject(document); 1303 if (lock == null) { 1304 updateAnnotationModelForRemoves(annotationModel); 1305 } else { 1306 synchronized (lock) { 1307 updateAnnotationModelForRemoves(annotationModel); 1308 } 1309 } 1310 } 1311 1312 1313 private void updateAnnotationModelForRemoves(IAnnotationModel annotationModel) { 1314 if (annotationModel instanceof IAnnotationModelExtension) { 1315 ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null); 1316 } else { 1317 for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++) { 1318 annotationModel.removeAnnotation(fOccurrenceAnnotations[i]); 1319 } 1320 } 1321 fOccurrenceAnnotations= null; 1322 } 1323 1324 protected void installOccurrencesFinder() { 1325 fMarkOccurrenceAnnotations= true; 1326 1327 if (getSelectionProvider() != null) { 1328 ISelection selection= getSelectionProvider().getSelection(); 1329 if (selection instanceof ITextSelection) { 1330 fForcedMarkOccurrencesSelection= (ITextSelection) selection; 1331 updateOccurrenceAnnotations(fForcedMarkOccurrencesSelection, getAntModel()); 1332 } 1333 } 1334 if (fOccurrencesFinderJobCanceler == null) { 1335 fOccurrencesFinderJobCanceler= new OccurrencesFinderJobCanceler(); 1336 fOccurrencesFinderJobCanceler.install(); 1337 } 1338 } 1339 1340 protected void uninstallOccurrencesFinder() { 1341 fMarkOccurrenceAnnotations= false; 1342 1343 if (fOccurrencesFinderJob != null) { 1344 fOccurrencesFinderJob.cancel(); 1345 fOccurrencesFinderJob= null; 1346 } 1347 1348 if (fOccurrencesFinderJobCanceler != null) { 1349 fOccurrencesFinderJobCanceler.uninstall(); 1350 fOccurrencesFinderJobCanceler= null; 1351 } 1352 1353 removeOccurrenceAnnotations(); 1354 } 1355 1356 public boolean isMarkingOccurrences() { 1357 return fMarkOccurrenceAnnotations; 1358 } 1359 1360 1361 1366 public void setInLinkedMode(boolean inLinkedMode, boolean effectsOccurrences) { 1367 if (inLinkedMode) { 1368 getAntModel().setShouldReconcile(false); 1369 if (effectsOccurrences) { 1370 uninstallOccurrencesFinder(); 1371 } 1372 } else { 1373 getAntModel().setShouldReconcile(true); 1374 if (effectsOccurrences) { 1375 installOccurrencesFinder(); 1376 } 1377 } 1378 } 1379} | Popular Tags |