1 11 12 package org.eclipse.jface.text; 13 14 import org.eclipse.swt.SWT; 15 import org.eclipse.swt.custom.StyledText; 16 import org.eclipse.swt.events.KeyEvent; 17 import org.eclipse.swt.events.KeyListener; 18 import org.eclipse.swt.events.MouseEvent; 19 import org.eclipse.swt.events.MouseListener; 20 import org.eclipse.swt.widgets.Display; 21 import org.eclipse.swt.widgets.Shell; 22 23 import org.eclipse.core.commands.ExecutionException; 24 import org.eclipse.core.commands.operations.IUndoContext; 25 26 import org.eclipse.text.undo.DocumentUndoEvent; 27 import org.eclipse.text.undo.DocumentUndoManager; 28 import org.eclipse.text.undo.DocumentUndoManagerRegistry; 29 import org.eclipse.text.undo.IDocumentUndoListener; 30 import org.eclipse.text.undo.IDocumentUndoManager; 31 32 import org.eclipse.jface.dialogs.MessageDialog; 33 34 35 56 public class TextViewerUndoManager implements IUndoManager, IUndoManagerExtension { 57 58 59 62 private class KeyAndMouseListener implements MouseListener, KeyListener { 63 64 67 public void mouseDoubleClick(MouseEvent e) { 68 } 69 70 74 public void mouseDown(MouseEvent e) { 75 if (e.button == 1) 76 if (isConnected()) 77 fDocumentUndoManager.commit(); 78 } 79 80 83 public void mouseUp(MouseEvent e) { 84 } 85 86 89 public void keyReleased(KeyEvent e) { 90 } 91 92 96 public void keyPressed(KeyEvent e) { 97 switch (e.keyCode) { 98 case SWT.ARROW_UP: 99 case SWT.ARROW_DOWN: 100 case SWT.ARROW_LEFT: 101 case SWT.ARROW_RIGHT: 102 if (isConnected()) { 103 fDocumentUndoManager.commit(); 104 } 105 break; 106 } 107 } 108 } 109 110 111 114 private class TextInputListener implements ITextInputListener { 115 116 119 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { 120 disconnectDocumentUndoManager(); 121 } 122 123 126 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { 127 connectDocumentUndoManager(newInput); 128 } 129 } 130 131 132 135 private class DocumentUndoListener implements IDocumentUndoListener { 136 137 140 public void documentUndoNotification(DocumentUndoEvent event ){ 141 if (!isConnected()) return; 142 143 int eventType= event.getEventType(); 144 if (((eventType & DocumentUndoEvent.ABOUT_TO_UNDO) != 0) || ((eventType & DocumentUndoEvent.ABOUT_TO_REDO) != 0)) { 145 if (event.isCompound()) { 146 ITextViewerExtension extension= null; 147 if (fTextViewer instanceof ITextViewerExtension) 148 extension= (ITextViewerExtension) fTextViewer; 149 150 if (extension != null) 151 extension.setRedraw(false); 152 } 153 fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable () { 154 public void run() { 155 if (fTextViewer instanceof TextViewer) 156 ((TextViewer)fTextViewer).ignoreAutoEditStrategies(true); 157 } 158 }); 159 160 } else if (((eventType & DocumentUndoEvent.UNDONE) != 0) || ((eventType & DocumentUndoEvent.REDONE) != 0)) { 161 fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable () { 162 public void run() { 163 if (fTextViewer instanceof TextViewer) 164 ((TextViewer)fTextViewer).ignoreAutoEditStrategies(false); 165 } 166 }); 167 if (event.isCompound()) { 168 ITextViewerExtension extension= null; 169 if (fTextViewer instanceof ITextViewerExtension) 170 extension= (ITextViewerExtension) fTextViewer; 171 172 if (extension != null) 173 extension.setRedraw(true); 174 } 175 176 if (fTextViewer != null) { 178 StyledText widget= fTextViewer.getTextWidget(); 179 if (widget != null && !widget.isDisposed() && (widget.isFocusControl())) selectAndReveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); 181 } 182 } 183 } 184 185 } 186 187 188 private KeyAndMouseListener fKeyAndMouseListener; 189 190 private TextInputListener fTextInputListener; 191 192 193 194 private ITextViewer fTextViewer; 195 196 197 private int fUndoLevel; 198 199 200 private IDocumentUndoManager fDocumentUndoManager; 201 202 203 private IDocument fDocument; 204 205 206 private IDocumentUndoListener fDocumentUndoListener; 207 208 213 public TextViewerUndoManager(int undoLevel) { 214 fUndoLevel= undoLevel; 215 } 216 217 222 private boolean isConnected() { 223 return fTextViewer != null && fDocumentUndoManager != null; 224 } 225 226 229 public void beginCompoundChange() { 230 if (isConnected()) { 231 fDocumentUndoManager.beginCompoundChange(); 232 } 233 } 234 235 236 239 public void endCompoundChange() { 240 if (isConnected()) { 241 fDocumentUndoManager.endCompoundChange(); 242 } 243 } 244 245 248 private void addListeners() { 249 StyledText text= fTextViewer.getTextWidget(); 250 if (text != null) { 251 fKeyAndMouseListener= new KeyAndMouseListener(); 252 text.addMouseListener(fKeyAndMouseListener); 253 text.addKeyListener(fKeyAndMouseListener); 254 fTextInputListener= new TextInputListener(); 255 fTextViewer.addTextInputListener(fTextInputListener); 256 } 257 } 258 259 262 private void removeListeners() { 263 StyledText text= fTextViewer.getTextWidget(); 264 if (text != null) { 265 if (fKeyAndMouseListener != null) { 266 text.removeMouseListener(fKeyAndMouseListener); 267 text.removeKeyListener(fKeyAndMouseListener); 268 fKeyAndMouseListener= null; 269 } 270 if (fTextInputListener != null) { 271 fTextViewer.removeTextInputListener(fTextInputListener); 272 fTextInputListener= null; 273 } 274 } 275 } 276 277 283 private void openErrorDialog(final String title, final Exception ex) { 284 Shell shell= null; 285 if (isConnected()) { 286 StyledText st= fTextViewer.getTextWidget(); 287 if (st != null && !st.isDisposed()) 288 shell= st.getShell(); 289 } 290 if (Display.getCurrent() != null) 291 MessageDialog.openError(shell, title, ex.getLocalizedMessage()); 292 else { 293 Display display; 294 final Shell finalShell= shell; 295 if (finalShell != null) 296 display= finalShell.getDisplay(); 297 else 298 display= Display.getDefault(); 299 display.syncExec(new Runnable () { 300 public void run() { 301 MessageDialog.openError(finalShell, title, ex.getLocalizedMessage()); 302 } 303 }); 304 } 305 } 306 307 310 public void setMaximalUndoLevel(int undoLevel) { 311 fUndoLevel= Math.max(0, undoLevel); 312 if (isConnected()) { 313 fDocumentUndoManager.setMaximalUndoLevel(fUndoLevel); 314 } 315 } 316 317 320 public void connect(ITextViewer textViewer) { 321 if (fTextViewer == null && textViewer != null) { 322 fTextViewer= textViewer; 323 addListeners(); 324 } 325 IDocument doc= fTextViewer.getDocument(); 326 connectDocumentUndoManager(doc); 327 } 328 329 332 public void disconnect() { 333 if (fTextViewer != null) { 334 removeListeners(); 335 fTextViewer= null; 336 } 337 disconnectDocumentUndoManager(); 338 } 339 340 343 public void reset() { 344 if (isConnected()) 345 fDocumentUndoManager.reset(); 346 347 } 348 349 352 public boolean redoable() { 353 if (isConnected()) 354 return fDocumentUndoManager.redoable(); 355 return false; 356 } 357 358 361 public boolean undoable() { 362 if (isConnected()) 363 return fDocumentUndoManager.undoable(); 364 return false; 365 } 366 367 370 public void redo() { 371 if (isConnected()) { 372 try { 373 fDocumentUndoManager.redo(); 374 } catch (ExecutionException ex) { 375 openErrorDialog(JFaceTextMessages.getString("DefaultUndoManager.error.redoFailed.title"), ex); } 377 } 378 } 379 380 383 public void undo() { 384 if (isConnected()) { 385 try { 386 fDocumentUndoManager.undo(); 387 } catch (ExecutionException ex) { 388 openErrorDialog(JFaceTextMessages.getString("DefaultUndoManager.error.undoFailed.title"), ex); } 390 } 391 } 392 393 399 private void selectAndReveal(int offset, int length) { 400 if (fTextViewer instanceof ITextViewerExtension5) { 401 ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer; 402 extension.exposeModelRange(new Region(offset, length)); 403 } else if (!fTextViewer.overlapsWithVisibleRegion(offset, length)) 404 fTextViewer.resetVisibleRegion(); 405 406 fTextViewer.setSelectedRange(offset, length); 407 fTextViewer.revealRange(offset, length); 408 } 409 410 413 public IUndoContext getUndoContext() { 414 if (isConnected()) { 415 return fDocumentUndoManager.getUndoContext(); 416 } 417 return null; 418 } 419 420 private void connectDocumentUndoManager(IDocument document) { 421 disconnectDocumentUndoManager(); 422 if (document != null) { 423 fDocument= document; 424 DocumentUndoManagerRegistry.connect(fDocument); 425 fDocumentUndoManager= DocumentUndoManagerRegistry.getDocumentUndoManager(fDocument); 426 fDocumentUndoManager.connect(this); 427 setMaximalUndoLevel(fUndoLevel); 428 fDocumentUndoListener= new DocumentUndoListener(); 429 fDocumentUndoManager.addDocumentUndoListener(fDocumentUndoListener); 430 } 431 } 432 433 private void disconnectDocumentUndoManager() { 434 if (fDocumentUndoManager != null) { 435 fDocumentUndoManager.disconnect(this); 436 DocumentUndoManagerRegistry.disconnect(fDocument); 437 fDocumentUndoManager.removeDocumentUndoListener(fDocumentUndoListener); 438 fDocumentUndoListener= null; 439 fDocumentUndoManager= null; 440 } 441 } 442 } 443 | Popular Tags |