| 1 15 package org.eclipse.ui.texteditor; 16 17 18 import java.lang.reflect.InvocationTargetException ; 19 import java.util.ArrayList ; 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.osgi.framework.Bundle; 27 28 import org.eclipse.swt.SWT; 29 import org.eclipse.swt.custom.BusyIndicator; 30 import org.eclipse.swt.custom.ST; 31 import org.eclipse.swt.custom.StyledText; 32 import org.eclipse.swt.custom.VerifyKeyListener; 33 import org.eclipse.swt.dnd.DND; 34 import org.eclipse.swt.dnd.DragSource; 35 import org.eclipse.swt.dnd.DragSourceAdapter; 36 import org.eclipse.swt.dnd.DragSourceEvent; 37 import org.eclipse.swt.dnd.DropTargetAdapter; 38 import org.eclipse.swt.dnd.DropTargetEvent; 39 import org.eclipse.swt.dnd.DropTargetListener; 40 import org.eclipse.swt.dnd.TextTransfer; 41 import org.eclipse.swt.dnd.Transfer; 42 import org.eclipse.swt.events.KeyEvent; 43 import org.eclipse.swt.events.KeyListener; 44 import org.eclipse.swt.events.MouseEvent; 45 import org.eclipse.swt.events.MouseListener; 46 import org.eclipse.swt.events.VerifyEvent; 47 import org.eclipse.swt.events.VerifyListener; 48 import org.eclipse.swt.graphics.Color; 49 import org.eclipse.swt.graphics.Font; 50 import org.eclipse.swt.graphics.FontData; 51 import org.eclipse.swt.graphics.GC; 52 import org.eclipse.swt.graphics.Image; 53 import org.eclipse.swt.graphics.ImageData; 54 import org.eclipse.swt.graphics.PaletteData; 55 import org.eclipse.swt.graphics.Point; 56 import org.eclipse.swt.graphics.RGB; 57 import org.eclipse.swt.widgets.Caret; 58 import org.eclipse.swt.widgets.Composite; 59 import org.eclipse.swt.widgets.Control; 60 import org.eclipse.swt.widgets.Display; 61 import org.eclipse.swt.widgets.Menu; 62 import org.eclipse.swt.widgets.Shell; 63 64 import org.eclipse.core.commands.operations.IOperationApprover; 65 import org.eclipse.core.commands.operations.IOperationHistory; 66 import org.eclipse.core.commands.operations.IUndoContext; 67 import org.eclipse.core.commands.operations.OperationHistoryFactory; 68 69 import org.eclipse.core.runtime.Assert; 70 import org.eclipse.core.runtime.CoreException; 71 import org.eclipse.core.runtime.IConfigurationElement; 72 import org.eclipse.core.runtime.ILog; 73 import org.eclipse.core.runtime.IProgressMonitor; 74 import org.eclipse.core.runtime.IStatus; 75 import org.eclipse.core.runtime.NullProgressMonitor; 76 import org.eclipse.core.runtime.Platform; 77 import org.eclipse.core.runtime.SafeRunner; 78 import org.eclipse.core.runtime.Status; 79 80 import org.eclipse.text.undo.DocumentUndoManagerRegistry; 81 import org.eclipse.text.undo.IDocumentUndoManager; 82 83 import org.eclipse.jface.action.Action; 84 import org.eclipse.jface.action.GroupMarker; 85 import org.eclipse.jface.action.IAction; 86 import org.eclipse.jface.action.IMenuListener; 87 import org.eclipse.jface.action.IMenuManager; 88 import org.eclipse.jface.action.IStatusLineManager; 89 import org.eclipse.jface.action.MenuManager; 90 import org.eclipse.jface.action.Separator; 91 import org.eclipse.jface.dialogs.ErrorDialog; 92 import org.eclipse.jface.dialogs.MessageDialog; 93 import org.eclipse.jface.internal.text.html.HTMLTextPresenter; 94 import org.eclipse.jface.operation.IRunnableWithProgress; 95 import org.eclipse.jface.preference.IPreferenceStore; 96 import org.eclipse.jface.preference.PreferenceConverter; 97 import org.eclipse.jface.resource.ImageDescriptor; 98 import org.eclipse.jface.resource.JFaceResources; 99 import org.eclipse.jface.util.IPropertyChangeListener; 100 import org.eclipse.jface.util.PropertyChangeEvent; 101 import org.eclipse.jface.util.SafeRunnable; 102 import org.eclipse.jface.viewers.IPostSelectionProvider; 103 import org.eclipse.jface.viewers.ISelection; 104 import org.eclipse.jface.viewers.ISelectionChangedListener; 105 import org.eclipse.jface.viewers.ISelectionProvider; 106 import org.eclipse.jface.viewers.SelectionChangedEvent; 107 import org.eclipse.jface.viewers.StructuredSelection; 108 import org.eclipse.jface.window.IShellProvider; 109 110 import org.eclipse.jface.text.AbstractInformationControlManager; 111 import org.eclipse.jface.text.BadLocationException; 112 import org.eclipse.jface.text.DefaultInformationControl; 113 import org.eclipse.jface.text.DefaultLineTracker; 114 import org.eclipse.jface.text.DocumentEvent; 115 import org.eclipse.jface.text.IDocument; 116 import org.eclipse.jface.text.IDocumentListener; 117 import org.eclipse.jface.text.IFindReplaceTarget; 118 import org.eclipse.jface.text.IFindReplaceTargetExtension; 119 import org.eclipse.jface.text.IInformationControl; 120 import org.eclipse.jface.text.IInformationControlCreator; 121 import org.eclipse.jface.text.IMarkRegionTarget; 122 import org.eclipse.jface.text.IRegion; 123 import org.eclipse.jface.text.IRewriteTarget; 124 import org.eclipse.jface.text.ISelectionValidator; 125 import org.eclipse.jface.text.ITextHover; 126 import org.eclipse.jface.text.ITextInputListener; 127 import org.eclipse.jface.text.ITextListener; 128 import org.eclipse.jface.text.ITextOperationTarget; 129 import org.eclipse.jface.text.ITextSelection; 130 import org.eclipse.jface.text.ITextViewer; 131 import org.eclipse.jface.text.ITextViewerExtension; 132 import org.eclipse.jface.text.ITextViewerExtension2; 133 import org.eclipse.jface.text.ITextViewerExtension4; 134 import org.eclipse.jface.text.ITextViewerExtension5; 135 import org.eclipse.jface.text.ITextViewerExtension6; 136 import org.eclipse.jface.text.ITextViewerExtension7; 137 import org.eclipse.jface.text.IUndoManager; 138 import org.eclipse.jface.text.IUndoManagerExtension; 139 import org.eclipse.jface.text.Position; 140 import org.eclipse.jface.text.Region; 141 import org.eclipse.jface.text.TabsToSpacesConverter; 142 import org.eclipse.jface.text.TextEvent; 143 import org.eclipse.jface.text.TextSelection; 144 import org.eclipse.jface.text.TextUtilities; 145 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; 146 import org.eclipse.jface.text.information.IInformationProvider; 147 import org.eclipse.jface.text.information.IInformationProviderExtension; 148 import org.eclipse.jface.text.information.IInformationProviderExtension2; 149 import org.eclipse.jface.text.information.InformationPresenter; 150 import org.eclipse.jface.text.link.LinkedModeModel; 151 import org.eclipse.jface.text.link.LinkedPosition; 152 import org.eclipse.jface.text.revisions.RevisionInformation; 153 import org.eclipse.jface.text.source.Annotation; 154 import org.eclipse.jface.text.source.CompositeRuler; 155 import org.eclipse.jface.text.source.IAnnotationHover; 156 import org.eclipse.jface.text.source.IAnnotationHoverExtension; 157 import org.eclipse.jface.text.source.IAnnotationModel; 158 import org.eclipse.jface.text.source.ILineRange; 159 import org.eclipse.jface.text.source.ISourceViewer; 160 import org.eclipse.jface.text.source.ISourceViewerExtension3; 161 import org.eclipse.jface.text.source.IVerticalRuler; 162 import org.eclipse.jface.text.source.IVerticalRulerColumn; 163 import org.eclipse.jface.text.source.IVerticalRulerExtension; 164 import org.eclipse.jface.text.source.IVerticalRulerInfo; 165 import org.eclipse.jface.text.source.SourceViewer; 166 import org.eclipse.jface.text.source.SourceViewerConfiguration; 167 import org.eclipse.jface.text.source.VerticalRuler; 168 169 import org.eclipse.ui.IActionBars; 170 import org.eclipse.ui.IEditorDescriptor; 171 import org.eclipse.ui.IEditorInput; 172 import org.eclipse.ui.IEditorPart; 173 import org.eclipse.ui.IEditorRegistry; 174 import org.eclipse.ui.IEditorSite; 175 import org.eclipse.ui.IKeyBindingService; 176 import org.eclipse.ui.IMemento; 177 import org.eclipse.ui.INavigationLocation; 178 import org.eclipse.ui.INavigationLocationProvider; 179 import org.eclipse.ui.IPartListener; 180 import org.eclipse.ui.IPartService; 181 import org.eclipse.ui.IPersistableEditor; 182 import org.eclipse.ui.IReusableEditor; 183 import org.eclipse.ui.ISaveablesLifecycleListener; 184 import org.eclipse.ui.ISaveablesSource; 185 import org.eclipse.ui.IWindowListener; 186 import org.eclipse.ui.IWorkbenchActionConstants; 187 import org.eclipse.ui.IWorkbenchPart; 188 import org.eclipse.ui.IWorkbenchWindow; 189 import org.eclipse.ui.PartInitException; 190 import org.eclipse.ui.PlatformUI; 191 import org.eclipse.ui.Saveable; 192 import org.eclipse.ui.SaveablesLifecycleEvent; 193 import org.eclipse.ui.actions.CommandNotMappedException; 194 import org.eclipse.ui.actions.ContributedAction; 195 import org.eclipse.ui.dialogs.PropertyDialogAction; 196 import org.eclipse.ui.dnd.IDragAndDropService; 197 import org.eclipse.ui.internal.texteditor.EditPosition; 198 import org.eclipse.ui.internal.texteditor.NLSUtility; 199 import org.eclipse.ui.internal.texteditor.TextEditorPlugin; 200 import org.eclipse.ui.internal.texteditor.rulers.StringSetSerializer; 201 import org.eclipse.ui.operations.LinearUndoViolationUserApprover; 202 import org.eclipse.ui.operations.NonLocalUndoUserApprover; 203 import org.eclipse.ui.operations.OperationHistoryActionHandler; 204 import org.eclipse.ui.operations.RedoActionHandler; 205 import org.eclipse.ui.operations.UndoActionHandler; 206 import org.eclipse.ui.part.EditorPart; 207 import org.eclipse.ui.texteditor.rulers.IColumnSupport; 208 import org.eclipse.ui.texteditor.rulers.IContributedRulerColumn; 209 import org.eclipse.ui.texteditor.rulers.RulerColumnDescriptor; 210 import org.eclipse.ui.texteditor.rulers.RulerColumnPreferenceAdapter; 211 import org.eclipse.ui.texteditor.rulers.RulerColumnRegistry; 212 213 214 238 public abstract class AbstractTextEditor extends EditorPart implements ITextEditor, IReusableEditor, ITextEditorExtension, ITextEditorExtension2, ITextEditorExtension3, ITextEditorExtension4, INavigationLocationProvider, ISaveablesSource, IPersistableEditor { 239 240 245 private static final String TAG_CONTRIBUTION_TYPE= "editorContribution"; 247 255 protected static final String TAG_SELECTION_OFFSET= "selectionOffset"; protected static final String TAG_SELECTION_LENGTH= "selectionLength"; private static final String TAG_SELECTION_HPIXEL= "selectionHPixel"; 260 261 267 private static final int WIDE_CARET_WIDTH= 2; 268 269 275 private static final int SINGLE_CARET_WIDTH= 1; 276 277 283 private static class TextInputListener implements ITextInputListener { 284 285 public boolean inputChanged; 286 287 288 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {} 289 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { inputChanged= true; } 290 } 291 292 295 class ElementStateListener implements IElementStateListener, IElementStateListenerExtension { 296 297 302 class Validator implements VerifyListener { 303 306 public void verifyText(VerifyEvent e) { 307 IDocument document= getDocumentProvider().getDocument(getEditorInput()); 308 final boolean[] documentChanged= new boolean[1]; 309 IDocumentListener listener= new IDocumentListener() { 310 public void documentAboutToBeChanged(DocumentEvent event) { 311 } 312 public void documentChanged(DocumentEvent event) { 313 documentChanged[0]= true; 314 } 315 }; 316 try { 317 if (document != null) 318 document.addDocumentListener(listener); 319 if (! validateEditorInputState() || documentChanged[0]) 320 e.doit= false; 321 } finally { 322 if (document != null) 323 document.removeDocumentListener(listener); 324 } 325 } 326 } 327 328 332 private Validator fValidator; 333 337 private Display fDisplay; 338 339 343 public void elementStateValidationChanged(final Object element, final boolean isStateValidated) { 344 if (element != null && element.equals(getEditorInput())) { 345 Runnable r= new Runnable () { 346 public void run() { 347 enableSanityChecking(true); 348 if (isStateValidated && fValidator != null) { 349 ISourceViewer viewer= fSourceViewer; 350 if (viewer != null) { 351 StyledText textWidget= viewer.getTextWidget(); 352 if (textWidget != null && !textWidget.isDisposed()) 353 textWidget.removeVerifyListener(fValidator); 354 fValidator= null; 355 enableStateValidation(false); 356 } 357 } else if (!isStateValidated && fValidator == null) { 358 ISourceViewer viewer= fSourceViewer; 359 if (viewer != null) { 360 StyledText textWidget= viewer.getTextWidget(); 361 if (textWidget != null && !textWidget.isDisposed()) { 362 fValidator= new Validator(); 363 enableStateValidation(true); 364 textWidget.addVerifyListener(fValidator); 365 } 366 } 367 } 368 } 369 }; 370 execute(r, false); 371 } 372 } 373 374 375 378 public void elementDirtyStateChanged(Object element, boolean isDirty) { 379 if (element != null && element.equals(getEditorInput())) { 380 Runnable r= new Runnable () { 381 public void run() { 382 enableSanityChecking(true); 383 firePropertyChange(PROP_DIRTY); 384 } 385 }; 386 execute(r, false); 387 } 388 } 389 390 393 public void elementContentAboutToBeReplaced(Object element) { 394 if (element != null && element.equals(getEditorInput())) { 395 Runnable r= new Runnable () { 396 public void run() { 397 enableSanityChecking(true); 398 rememberSelection(); 399 resetHighlightRange(); 400 } 401 }; 402 execute(r, false); 403 } 404 } 405 406 409 public void elementContentReplaced(Object element) { 410 if (element != null && element.equals(getEditorInput())) { 411 Runnable r= new Runnable () { 412 public void run() { 413 enableSanityChecking(true); 414 firePropertyChange(PROP_DIRTY); 415 restoreSelection(); 416 handleElementContentReplaced(); 417 } 418 }; 419 execute(r, false); 420 } 421 } 422 423 426 public void elementDeleted(Object deletedElement) { 427 if (deletedElement != null && deletedElement.equals(getEditorInput())) { 428 Runnable r= new Runnable () { 429 public void run() { 430 enableSanityChecking(true); 431 close(false); 432 } 433 }; 434 execute(r, false); 435 } 436 } 437 438 441 public void elementMoved(final Object originalElement, final Object movedElement) { 442 if (originalElement != null && originalElement.equals(getEditorInput())) { 443 final boolean doValidationAsync= Display.getCurrent() != null; 444 Runnable r= new Runnable () { 445 public void run() { 446 enableSanityChecking(true); 447 448 if (fSourceViewer == null) 449 return; 450 451 if (!canHandleMove((IEditorInput) originalElement, (IEditorInput) movedElement)) { 452 close(true); 453 return; 454 } 455 456 if (movedElement == null || movedElement instanceof IEditorInput) { 457 rememberSelection(); 458 459 final IDocumentProvider d= getDocumentProvider(); 460 final String previousContent; 461 IDocumentUndoManager previousUndoManager=null; 462 IDocument changed= null; 463 boolean wasDirty= isDirty(); 464 changed= d.getDocument(getEditorInput()); 465 if (changed != null) { 466 if (wasDirty) 467 previousContent= changed.get(); 468 else 469 previousContent= null; 470 471 previousUndoManager= DocumentUndoManagerRegistry.getDocumentUndoManager(changed); 472 if (previousUndoManager != null) 473 previousUndoManager.connect(this); 474 } 475 else 476 previousContent= null; 477 478 setInput((IEditorInput) movedElement); 479 480 if (previousUndoManager != null) { 483 IDocument newDocument= getDocumentProvider().getDocument(movedElement); 484 if (newDocument != null) { 485 IDocumentUndoManager newUndoManager= DocumentUndoManagerRegistry.getDocumentUndoManager(newDocument); 486 if (newUndoManager != null) 487 newUndoManager.transferUndoHistory(previousUndoManager); 488 } 489 previousUndoManager.disconnect(this); 490 } 491 492 if (wasDirty && changed != null) { 493 Runnable r2= new Runnable () { 494 public void run() { 495 validateState(getEditorInput()); 496 d.getDocument(getEditorInput()).set(previousContent); 497 updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE); 498 restoreSelection(); 499 } 500 }; 501 execute(r2, doValidationAsync); 502 } else 503 restoreSelection(); 504 505 } 506 } 507 }; 508 execute(r, false); 509 } 510 } 511 512 516 public void elementStateChanging(Object element) { 517 if (element != null && element.equals(getEditorInput())) 518 enableSanityChecking(false); 519 } 520 521 525 public void elementStateChangeFailed(Object element) { 526 if (element != null && element.equals(getEditorInput())) 527 enableSanityChecking(true); 528 } 529 530 541 private void execute(Runnable runnable, boolean postAsync) { 542 if (postAsync || Display.getCurrent() == null) { 543 if (fDisplay == null) 544 fDisplay= getSite().getShell().getDisplay(); 545 fDisplay.asyncExec(runnable); 546 } else 547 runnable.run(); 548 } 549 } 550 551 555 class TextListener implements ITextListener, ITextInputListener { 556 557 558 private Runnable fRunnable= new Runnable () { 559 public void run() { 560 fIsRunnablePosted= false; 561 562 if (fSourceViewer != null) { 563 updateContentDependentActions(); 564 565 if (isDirty() && fUpdateLastEditPosition) { 567 fUpdateLastEditPosition= false; 568 ISelection sel= getSelectionProvider().getSelection(); 569 IEditorInput input= getEditorInput(); 570 IDocument document= getDocumentProvider().getDocument(input); 571 572 if (fLocalLastEditPosition != null) { 573 document.removePosition(fLocalLastEditPosition); 574 fLocalLastEditPosition= null; 575 } 576 577 if (sel instanceof ITextSelection && !sel.isEmpty()) { 578 ITextSelection s= (ITextSelection) sel; 579 fLocalLastEditPosition= new Position(s.getOffset(), s.getLength()); 580 try { 581 document.addPosition(fLocalLastEditPosition); 582 } catch (BadLocationException ex) { 583 fLocalLastEditPosition= null; 584 } 585 } 586 TextEditorPlugin.getDefault().setLastEditPosition(new EditPosition(input, getEditorSite().getId(), fLocalLastEditPosition)); 587 } 588 } 589 } 590 }; 591 592 593 private Display fDisplay; 594 598 private Position fLocalLastEditPosition; 599 603 private boolean fIsRunnablePosted= false; 604 608 private boolean fUpdateLastEditPosition= false; 609 610 613 public void textChanged(TextEvent event) { 614 615 620 621 if (fDisplay == null) 622 fDisplay= getSite().getShell().getDisplay(); 623 624 if (event.getDocumentEvent() != null) 625 fUpdateLastEditPosition= true; 626 627 if (!fIsRunnablePosted) { 628 fIsRunnablePosted= true; 629 fDisplay.asyncExec(fRunnable); 630 } 631 } 632 633 636 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 637 if (oldInput != null && fLocalLastEditPosition != null) { 638 oldInput.removePosition(fLocalLastEditPosition); 639 fLocalLastEditPosition= null; 640 } 641 } 642 643 646 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 647 } 648 } 649 650 653 class PropertyChangeListener implements IPropertyChangeListener { 654 657 public void propertyChange(PropertyChangeEvent event) { 658 handlePreferenceStoreChanged(event); 659 } 660 } 661 662 666 class FontPropertyChangeListener implements IPropertyChangeListener { 667 |