1 11 package org.eclipse.pde.internal.ui.editor.context; 12 import java.lang.reflect.InvocationTargetException ; 13 import java.util.ArrayList ; 14 15 import org.eclipse.core.filebuffers.IDocumentSetupParticipant; 16 import org.eclipse.core.resources.IFile; 17 import org.eclipse.core.resources.IResource; 18 import org.eclipse.core.resources.IWorkspace; 19 import org.eclipse.core.resources.ResourcesPlugin; 20 import org.eclipse.core.runtime.CoreException; 21 import org.eclipse.core.runtime.IPath; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.jface.dialogs.ErrorDialog; 25 import org.eclipse.jface.dialogs.IMessageProvider; 26 import org.eclipse.jface.text.BadLocationException; 27 import org.eclipse.jface.text.IDocument; 28 import org.eclipse.jface.text.TextUtilities; 29 import org.eclipse.jface.text.source.IAnnotationModel; 30 import org.eclipse.jface.window.Window; 31 import org.eclipse.osgi.util.NLS; 32 import org.eclipse.pde.core.IBaseModel; 33 import org.eclipse.pde.core.IEditable; 34 import org.eclipse.pde.core.IModelChangeProvider; 35 import org.eclipse.pde.core.IModelChangedEvent; 36 import org.eclipse.pde.core.IModelChangedListener; 37 import org.eclipse.pde.internal.core.text.IEditingModel; 38 import org.eclipse.pde.internal.core.util.PropertiesUtil; 39 import org.eclipse.pde.internal.ui.PDEPlugin; 40 import org.eclipse.pde.internal.ui.PDEUIMessages; 41 import org.eclipse.pde.internal.ui.editor.PDEFormEditor; 42 import org.eclipse.pde.internal.ui.editor.PDEStorageDocumentProvider; 43 import org.eclipse.swt.widgets.Shell; 44 import org.eclipse.text.edits.InsertEdit; 45 import org.eclipse.text.edits.MalformedTreeException; 46 import org.eclipse.text.edits.MoveSourceEdit; 47 import org.eclipse.text.edits.MultiTextEdit; 48 import org.eclipse.text.edits.TextEdit; 49 import org.eclipse.ui.IEditorInput; 50 import org.eclipse.ui.IFileEditorInput; 51 import org.eclipse.ui.PlatformUI; 52 import org.eclipse.ui.actions.WorkspaceModifyOperation; 53 import org.eclipse.ui.dialogs.SaveAsDialog; 54 import org.eclipse.ui.editors.text.ForwardingDocumentProvider; 55 import org.eclipse.ui.part.FileEditorInput; 56 import org.eclipse.ui.texteditor.IDocumentProvider; 57 import org.eclipse.ui.texteditor.IElementStateListener; 58 61 public abstract class InputContext { 62 63 private PDEFormEditor fEditor; 64 private IEditorInput fEditorInput; 65 private IBaseModel fModel; 66 private IModelChangedListener fModelListener; 67 private IDocumentProvider fDocumentProvider; 68 private IElementStateListener fElementListener; 69 protected ArrayList fEditOperations = new ArrayList (); 70 71 private boolean fValidated; 72 private boolean fPrimary; 73 private boolean fIsSourceMode; 74 private boolean fMustSynchronize; 75 76 class ElementListener implements IElementStateListener { 77 public void elementContentAboutToBeReplaced(Object element) { 78 } 79 public void elementContentReplaced(Object element) { 80 doRevert(); 81 } 82 public void elementDeleted(Object element) { 83 dispose(); 84 } 85 public void elementDirtyStateChanged(Object element, boolean isDirty) { 86 fMustSynchronize=true; 87 } 88 public void elementMoved(Object originalElement, Object movedElement) { 89 dispose(); 90 fEditor.close(true); 91 } 92 } 93 public InputContext(PDEFormEditor editor, IEditorInput input, boolean primary) { 94 this.fEditor = editor; 95 this.fEditorInput = input; 96 setPrimary(primary); 97 } 98 public abstract String getId(); 99 100 public IEditorInput getInput() { 101 return fEditorInput; 102 } 103 public PDEFormEditor getEditor() { 104 return fEditor; 105 } 106 public IBaseModel getModel() { 107 return fModel; 108 } 109 public IDocumentProvider getDocumentProvider() { 110 return fDocumentProvider; 111 } 112 113 private IDocumentProvider createDocumentProvider(IEditorInput input) { 114 if (input instanceof IFileEditorInput) { 115 return new ForwardingDocumentProvider( 116 getPartitionName(), 117 getDocumentSetupParticipant(), 118 PDEPlugin.getDefault().getTextFileDocumentProvider()); 119 } 120 return new PDEStorageDocumentProvider(getDocumentSetupParticipant()); 121 } 122 123 protected IDocumentSetupParticipant getDocumentSetupParticipant() { 124 return new IDocumentSetupParticipant() { 125 public void setup(IDocument document) { 126 } 127 }; 128 } 129 130 protected abstract String getPartitionName(); 131 132 protected abstract String getDefaultCharset(); 133 134 protected abstract IBaseModel createModel(IEditorInput input) throws CoreException; 135 136 protected void create() { 137 fDocumentProvider = createDocumentProvider(fEditorInput); 138 try { 139 fDocumentProvider.connect(fEditorInput); 140 fModel = createModel(fEditorInput); 141 if (fModel instanceof IModelChangeProvider) { 142 fModelListener = new IModelChangedListener() { 143 public void modelChanged(IModelChangedEvent e) { 144 if (e.getChangeType() != IModelChangedEvent.WORLD_CHANGED) { 145 if (!fEditor.getLastDirtyState()) 146 fEditor.fireSaveNeeded(fEditorInput, true); 147 IModelChangeProvider provider = e.getChangeProvider(); 148 if (provider instanceof IEditingModel) { 149 if (((IEditingModel)provider).isDirty()) 153 addTextEditOperation(fEditOperations, e); 154 } 155 } 156 } 157 }; 158 ((IModelChangeProvider) fModel).addModelChangedListener(fModelListener); 159 } 160 161 IAnnotationModel amodel = fDocumentProvider 162 .getAnnotationModel(fEditorInput); 163 if (amodel != null) 164 amodel.connect(fDocumentProvider.getDocument(fEditorInput)); 165 fElementListener = new ElementListener(); 166 fDocumentProvider.addElementStateListener(fElementListener); 167 } catch (CoreException e) { 168 PDEPlugin.logException(e); 169 } 170 171 } 172 173 public synchronized boolean validateEdit() { 174 if (!fValidated) { 175 if (fEditorInput instanceof IFileEditorInput) { 176 IFile file = ((IFileEditorInput) fEditorInput).getFile(); 177 if (file.isReadOnly()) { 178 Shell shell = fEditor.getEditorSite().getShell(); 179 IStatus validateStatus = PDEPlugin.getWorkspace().validateEdit( 180 new IFile[]{file}, shell); 181 fValidated=true; if (validateStatus.getSeverity() != IStatus.OK) 183 ErrorDialog.openError(shell, fEditor.getTitle(), null, 184 validateStatus); 185 return validateStatus.getSeverity() == IStatus.OK; 186 } 187 } 188 } 189 return true; 190 } 191 public void doSave(IProgressMonitor monitor) { 192 try { 193 IDocument doc = fDocumentProvider.getDocument(fEditorInput); 194 fDocumentProvider.aboutToChange(fEditorInput); 195 flushModel(doc); 196 fDocumentProvider.saveDocument(monitor, fEditorInput, doc, true); 197 fDocumentProvider.changed(fEditorInput); 198 fValidated=false; 199 } 200 catch (CoreException e) { 201 PDEPlugin.logException(e); 202 } 203 } 204 205 protected abstract void addTextEditOperation(ArrayList ops, IModelChangedEvent event); 206 207 public void flushEditorInput() { 208 if (fEditOperations.size() > 0) { 209 IDocument doc = fDocumentProvider.getDocument(fEditorInput); 210 fDocumentProvider.aboutToChange(fEditorInput); 211 flushModel(doc); 212 fDocumentProvider.changed(fEditorInput); 213 fValidated=false; 214 } 215 } 216 217 protected void flushModel(IDocument doc) { 218 boolean flushed = true; 219 if (fEditOperations.size() > 0) { 220 try { 221 MultiTextEdit edit = new MultiTextEdit(); 222 if (isNewlineNeeded(doc)) 223 insert(edit, new InsertEdit(doc.getLength(), TextUtilities.getDefaultLineDelimiter(doc))); 224 for (int i = 0; i < fEditOperations.size(); i++) { 225 insert(edit, (TextEdit)fEditOperations.get(i)); 226 } 227 if (fModel instanceof IEditingModel) 228 ((IEditingModel)fModel).setStale(true); 229 edit.apply(doc); 230 fEditOperations.clear(); 231 } catch (MalformedTreeException e) { 232 PDEPlugin.logException(e); 233 flushed = false; 234 } catch (BadLocationException e) { 235 PDEPlugin.logException(e); 236 flushed = false; 237 } 238 } 239 if (flushed && 244 (fModel instanceof IEditable)) { 245 ((IEditable)fModel).setDirty(false); 246 } 247 } 248 249 protected boolean isNewlineNeeded(IDocument doc) throws BadLocationException { 250 return PropertiesUtil.isNewlineNeeded(doc); 251 } 252 253 protected static void insert(TextEdit parent, TextEdit edit) { 254 if (!parent.hasChildren()) { 255 parent.addChild(edit); 256 if (edit instanceof MoveSourceEdit) { 257 parent.addChild(((MoveSourceEdit)edit).getTargetEdit()); 258 } 259 return; 260 } 261 TextEdit[] children= parent.getChildren(); 262 for (int i= 0; i < children.length; i++) { 264 TextEdit child= children[i]; 265 if (covers(child, edit)) { 266 insert(child, edit); 267 return; 268 } 269 } 270 for (int i= children.length - 1; i >= 0; i--) { 273 TextEdit child= children[i]; 274 if (covers(edit, child)) { 275 parent.removeChild(i); 276 edit.addChild(child); 277 } 278 } 279 parent.addChild(edit); 280 if (edit instanceof MoveSourceEdit) { 281 parent.addChild(((MoveSourceEdit)edit).getTargetEdit()); 282 } 283 } 284 285 protected static boolean covers(TextEdit thisEdit, TextEdit otherEdit) { 286 if (thisEdit.getLength() == 0) return false; 288 289 int thisOffset= thisEdit.getOffset(); 290 int thisEnd= thisEdit.getExclusiveEnd(); 291 if (otherEdit.getLength() == 0) { 292 int otherOffset= otherEdit.getOffset(); 293 return thisOffset < otherOffset && otherOffset < thisEnd; 294 } 295 int otherOffset= otherEdit.getOffset(); 296 int otherEnd= otherEdit.getExclusiveEnd(); 297 return thisOffset <= otherOffset && otherEnd <= thisEnd; 298 } 299 300 public boolean mustSave() { 301 if (!fIsSourceMode) { 302 if (fModel instanceof IEditable) { 303 if (((IEditable)fModel).isDirty()) { 304 return true; 305 } 306 } 307 } 308 return fEditOperations.size() > 0 || fDocumentProvider.canSaveDocument(fEditorInput); 309 } 310 311 public void dispose() { 312 IAnnotationModel amodel = fDocumentProvider.getAnnotationModel(fEditorInput); 313 if (amodel != null) 314 amodel.disconnect(fDocumentProvider.getDocument(fEditorInput)); 315 fDocumentProvider.removeElementStateListener(fElementListener); 316 fDocumentProvider.disconnect(fEditorInput); 317 if (fModelListener != null && fModel instanceof IModelChangeProvider) { 318 ((IModelChangeProvider) fModel) 319 .removeModelChangedListener(fModelListener); 320 } 323 if (fModel!=null) 324 fModel.dispose(); 325 } 326 329 public boolean isPrimary() { 330 return fPrimary; 331 } 332 335 public void setPrimary(boolean primary) { 336 this.fPrimary = primary; 337 } 338 339 public boolean setSourceEditingMode(boolean sourceMode) { 340 fIsSourceMode = sourceMode; 341 if (sourceMode) { 342 flushModel(fDocumentProvider.getDocument(fEditorInput)); 348 fMustSynchronize=true; 349 return true; 350 } 351 return synchronizeModelIfNeeded(); 356 } 357 358 private boolean synchronizeModelIfNeeded() { 359 if (fMustSynchronize) { 360 boolean result = synchronizeModel(fDocumentProvider.getDocument(fEditorInput)); 361 fMustSynchronize=false; 362 return result; 363 } 364 return true; 365 } 366 367 public void doRevert() { 368 fMustSynchronize=true; 369 synchronizeModelIfNeeded(); 370 375 } 376 377 public boolean isInSourceMode() { 378 return fIsSourceMode; 379 } 380 381 public boolean isModelCorrect() { 382 synchronizeModelIfNeeded(); 383 return fModel!=null ? fModel.isValid() : false; 384 } 385 386 protected boolean synchronizeModel(IDocument doc) { 387 return true; 388 } 389 public boolean matches(IResource resource) { 390 if (fEditorInput instanceof IFileEditorInput) { 391 IFileEditorInput finput = (IFileEditorInput)fEditorInput; 392 IFile file = finput.getFile(); 393 if (file.equals(resource)) 394 return true; 395 } 396 return false; 397 } 398 401 public boolean isValidated() { 402 return fValidated; 403 } 404 407 public void setValidated(boolean validated) { 408 this.fValidated = validated; 409 } 410 411 public String getLineDelimiter() { 412 if (fDocumentProvider != null) { 413 IDocument document = fDocumentProvider.getDocument(fEditorInput); 414 if (document != null) { 415 return TextUtilities.getDefaultLineDelimiter(document); 416 } 417 } 418 return System.getProperty("line.separator"); } 420 421 425 private void updateInput(IEditorInput newInput) throws CoreException { 426 deinitializeDocumentProvider(); 427 fEditorInput = newInput; 428 initializeDocumentProvider(); 429 } 430 431 434 private void deinitializeDocumentProvider() { 435 IAnnotationModel amodel = 436 fDocumentProvider.getAnnotationModel(fEditorInput); 437 if (amodel != null) { 438 amodel.disconnect(fDocumentProvider.getDocument(fEditorInput)); 439 } 440 fDocumentProvider.removeElementStateListener(fElementListener); 441 fDocumentProvider.disconnect(fEditorInput); 442 } 443 444 447 private void initializeDocumentProvider() throws CoreException { 448 fDocumentProvider.connect(fEditorInput); 449 IAnnotationModel amodel = fDocumentProvider.getAnnotationModel(fEditorInput); 450 if (amodel != null) { 451 amodel.connect(fDocumentProvider.getDocument(fEditorInput)); 452 } 453 fDocumentProvider.addElementStateListener(fElementListener); 454 } 455 456 459 public void doSaveAs(IProgressMonitor monitor) throws Exception { 460 Shell shell = getEditor().getSite().getShell(); 462 SaveAsDialog dialog = new SaveAsDialog(shell); 464 IFile file = null; 466 if (fEditorInput instanceof IFileEditorInput) { 467 file = ((IFileEditorInput) fEditorInput).getFile(); 468 dialog.setOriginalFile(file); 469 } 470 dialog.create(); 472 if (fDocumentProvider.isDeleted(fEditorInput) && 474 (file != null)) { 475 String message = NLS.bind(PDEUIMessages.InputContext_errorMessageFileDoesNotExist, file.getName()); 476 dialog.setErrorMessage(null); 477 dialog.setMessage(message, IMessageProvider.WARNING); 478 } 479 if (dialog.open() == Window.OK) { 481 IPath path = dialog.getResult(); 483 handleSaveAs(monitor, path); 484 } 485 } 486 487 495 private void handleSaveAs(IProgressMonitor monitor, IPath path) 496 throws Exception , CoreException, InterruptedException , 497 InvocationTargetException { 498 if (path == null) { 500 monitor.setCanceled(true); 501 throw new Exception (PDEUIMessages.InputContext_errorMessageLocationNotSet); 502 } 503 IWorkspace workspace = ResourcesPlugin.getWorkspace(); 505 IFile newFile = workspace.getRoot().getFile(path); 506 final IEditorInput newInput = new FileEditorInput(newFile); 508 fDocumentProvider.aboutToChange(newInput); 510 flushModel(fDocumentProvider.getDocument(fEditorInput)); 512 try { 513 PlatformUI.getWorkbench().getProgressService().busyCursorWhile( 515 createWorkspaceModifyOperation(newInput)); 516 monitor.setCanceled(false); 517 updateInput(newInput); 519 } catch (InterruptedException e) { 520 monitor.setCanceled(true); 521 throw e; 522 } catch (InvocationTargetException e) { 523 monitor.setCanceled(true); 524 throw e; 525 } finally { 526 fDocumentProvider.changed(newInput); 527 } 528 } 529 530 534 private WorkspaceModifyOperation createWorkspaceModifyOperation( 535 final IEditorInput newInput) { 536 WorkspaceModifyOperation operation = new WorkspaceModifyOperation() { 537 public void execute(final IProgressMonitor monitor) throws CoreException { 538 fDocumentProvider.saveDocument( 541 monitor, 542 newInput, 544 fDocumentProvider.getDocument(fEditorInput), 546 true); 547 } 548 }; 549 return operation; 550 } 551 552 } 553 | Popular Tags |