Index: src/org/eclipse/jface/text/DefaultDocumentAdapter.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/DefaultDocumentAdapter.java,v
retrieving revision 1.8
diff -u -r1.8 DefaultDocumentAdapter.java
--- src/org/eclipse/jface/text/DefaultDocumentAdapter.java 17 Jun 2005 15:49:07 -0000 1.8
+++ src/org/eclipse/jface/text/DefaultDocumentAdapter.java 1 Sep 2005 17:45:37 -0000
@@ -87,8 +87,13 @@
if (!fIsForwarding) {
fDocumentClone= null;
- fOriginalContent= fDocument.get();
- fOriginalLineDelimiters= fDocument.getLegalLineDelimiters();
+ if (fDocument != null) {
+ fOriginalContent= fDocument.get();
+ fOriginalLineDelimiters= fDocument.getLegalLineDelimiters();
+ } else {
+ fOriginalContent= null;
+ fOriginalLineDelimiters= null;
+ }
}
if (fDocument != null)
Index: src/org/eclipse/jface/text/source/SourceViewerConfiguration.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewerConfiguration.java,v
retrieving revision 1.19
diff -u -r1.19 SourceViewerConfiguration.java
--- src/org/eclipse/jface/text/source/SourceViewerConfiguration.java 21 Jun 2005 20:17:35 -0000 1.19
+++ src/org/eclipse/jface/text/source/SourceViewerConfiguration.java 1 Sep 2005 17:45:39 -0000
@@ -28,6 +28,7 @@
import org.eclipse.jface.text.ITextDoubleClickStrategy;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.IUndoManager;
+import org.eclipse.jface.text.SharedDocumentUndoManager;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.hyperlink.DefaultHyperlinkPresenter;
@@ -87,6 +88,10 @@
* @return an undo manager or null
if no undo/redo should not be supported
*/
public IUndoManager getUndoManager(ISourceViewer sourceViewer) {
+ // Temporary variable to leave both styles in the code for now
+ boolean useSharedUndoManager = true;
+ if (useSharedUndoManager)
+ return new SharedDocumentUndoManager(25);
return new DefaultUndoManager(25);
}
Index: src/org/eclipse/jface/text/SharedDocumentUndoManager.java
===================================================================
RCS file: src/org/eclipse/jface/text/SharedDocumentUndoManager.java
diff -N src/org/eclipse/jface/text/SharedDocumentUndoManager.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/jface/text/SharedDocumentUndoManager.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jface.text;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.operations.IUndoContext;
+import org.eclipse.core.commands.operations.OperationHistoryFactory;
+import org.eclipse.core.runtime.IAdaptable;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+
+
+/**
+ * Shared document implementation of {@link org.eclipse.jface.text.IUndoManager}.
+ *
+ * It registers with the connected text viewer as text input listener, and obtains + * its undo manager from the current document. It also monitors mouse and keyboard + * activities in order to partition the stream of text changes into undo-able + * edit commands. + *
+ * This class is not intended to be subclassed. + *
+ * + * @see org.eclipse.jface.text.ITextViewer + * @see org.eclipse.jface.text.ITextInputListener + * @see MouseListener + * @see KeyListener + * @see DocumentUndoManager + * + * @since 3.2 + */ +public class SharedDocumentUndoManager implements IUndoManager, IUndoManagerExtension { + + /** + * Internal listener to mouse and key events. + */ + class KeyAndMouseListener implements MouseListener, KeyListener { + + /* + * @see MouseListener#mouseDoubleClick + */ + public void mouseDoubleClick(MouseEvent e) { + } + + /* + * If the right mouse button is pressed, the current editing command is closed + * @see MouseListener#mouseDown + */ + public void mouseDown(MouseEvent e) { + if (e.button == 1) + if (isConnected()) + fDocumentUndoManager.commit(); + } + + /* + * @see MouseListener#mouseUp + */ + public void mouseUp(MouseEvent e) { + } + + /* + * @see KeyListener#keyPressed + */ + public void keyReleased(KeyEvent e) { + } + + /* + * On cursor keys, the current editing command is closed + * @see KeyListener#keyPressed + */ + public void keyPressed(KeyEvent e) { + switch (e.keyCode) { + case SWT.ARROW_UP: + case SWT.ARROW_DOWN: + case SWT.ARROW_LEFT: + case SWT.ARROW_RIGHT: + if (isConnected()) { + fDocumentUndoManager.commit(); + } + break; + } + } + } + + /** + * Internal text input listener. + */ + class TextInputListener implements ITextInputListener { + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) { + if (oldInput != null && fDocumentUndoManager != null) { + fDocumentUndoManager.disconnect(SharedDocumentUndoManager.this); + fDocumentUndoManager.removeDocumentUndoListener(fDocumentUndoListener); + fDocumentUndoListener= null; + fDocumentUndoManager= null; + } + } + + /* + * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument) + */ + public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { + if (newInput instanceof IDocumentExtension5) { + fDocumentUndoManager= ((IDocumentExtension5)newInput).getUndoManager(); + fDocumentUndoManager.connect(SharedDocumentUndoManager.this); + setMaximalUndoLevel(fUndoLevel); + fDocumentUndoListener= new DocumentUndoListener(); + fDocumentUndoManager.addDocumentUndoListener(fDocumentUndoListener); + } + } + } + + /** + * Internal document undo listener. + */ + class DocumentUndoListener implements IDocumentUndoListener { + + /* + * @see org.eclipse.jface.text.IDocumentUndoListener#documentUndoNotification(DocumentUndoEvent) + */ + public void documentUndoNotification(DocumentUndoEvent event ){ + if (!isConnected()) return; + + int eventType= event.getEventType(); + if (((eventType & DocumentUndoEvent.ABOUT_TO_UNDO) != 0) || ((eventType & DocumentUndoEvent.ABOUT_TO_REDO) != 0)) { + if (event.isCompound()) { + ITextViewerExtension extension= null; + if (fTextViewer instanceof ITextViewerExtension) + extension= (ITextViewerExtension) fTextViewer; + + if (extension != null) + extension.setRedraw(false); + } + fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { + public void run() { + if (fTextViewer instanceof TextViewer) + ((TextViewer)fTextViewer).ignoreAutoEditStrategies(true); + } + }); + + } else if (((eventType & DocumentUndoEvent.UNDONE) != 0) || ((eventType & DocumentUndoEvent.REDONE) != 0)) { + fTextViewer.getTextWidget().getDisplay().syncExec(new Runnable() { + public void run() { + if (fTextViewer instanceof TextViewer) + ((TextViewer)fTextViewer).ignoreAutoEditStrategies(false); + } + }); + if (event.isCompound()) { + ITextViewerExtension extension= null; + if (fTextViewer instanceof ITextViewerExtension) + extension= (ITextViewerExtension) fTextViewer; + + if (extension != null) + extension.setRedraw(true); + } + // it it can be determined that the undo originated in this + // viewer, select and reveal the text. + IAdaptable uiInfo = event.getInfoAdapter(); + if (uiInfo != null) { + ITextViewer viewer = (ITextViewer)(uiInfo.getAdapter(ITextViewer.class)); + if (viewer == fTextViewer) + selectAndReveal(event.getOffset(), event.getText() == null ? 0 : event.getText().length()); + } + } + } + + } + + /** The internal key and mouse event listener */ + private KeyAndMouseListener fKeyAndMouseListener; + /** The internal text input listener */ + private TextInputListener fTextInputListener; + + + /** The text viewer the undo manager is connected to */ + private ITextViewer fTextViewer; + + /** The undo level */ + private int fUndoLevel; + + /** The document undo manager that is active */ + private IDocumentUndoManager fDocumentUndoManager; + + /** The document undo listener */ + private IDocumentUndoListener fDocumentUndoListener; + + /** + * Creates a new undo manager who remembers the specified number of edit commands. + * + * @param undoLevel the length of this manager's history + */ + public SharedDocumentUndoManager(int undoLevel) { + fUndoLevel= undoLevel; + } + + /** + * Returns whether this undo manager is connected to a text viewer. + * + * @returntrue
if connected, false
otherwise
+ * @since 3.1
+ */
+ private boolean isConnected() {
+ return fTextViewer != null && fDocumentUndoManager != null;
+ }
+
+ /*
+ * @see IUndoManager#beginCompoundChange
+ */
+ public void beginCompoundChange() {
+ if (isConnected()) {
+ fDocumentUndoManager.beginCompoundChange();
+ }
+ }
+
+
+ /*
+ * @see IUndoManager#endCompoundChange
+ */
+ public void endCompoundChange() {
+ if (isConnected()) {
+ fDocumentUndoManager.endCompoundChange();
+ }
+ }
+
+ /**
+ * Registers all necessary listeners with the text viewer.
+ */
+ private void addListeners() {
+ StyledText text= fTextViewer.getTextWidget();
+ if (text != null) {
+ fKeyAndMouseListener= new KeyAndMouseListener();
+ text.addMouseListener(fKeyAndMouseListener);
+ text.addKeyListener(fKeyAndMouseListener);
+ fTextInputListener= new TextInputListener();
+ fTextViewer.addTextInputListener(fTextInputListener);
+ }
+ }
+
+ /**
+ * Unregister all previously installed listeners from the text viewer.
+ */
+ private void removeListeners() {
+ StyledText text= fTextViewer.getTextWidget();
+ if (text != null) {
+ if (fKeyAndMouseListener != null) {
+ text.removeMouseListener(fKeyAndMouseListener);
+ text.removeKeyListener(fKeyAndMouseListener);
+ fKeyAndMouseListener= null;
+ }
+ if (fTextInputListener != null) {
+ fTextViewer.removeTextInputListener(fTextInputListener);
+ fTextInputListener= null;
+ }
+ }
+ }
+
+ /**
+ * Shows the given exception in an error dialog.
+ *
+ * @param title the dialog title
+ * @param ex the exception
+ * @since 3.1
+ */
+ private void openErrorDialog(final String title, final Exception ex) {
+ Shell shell= null;
+ if (isConnected()) {
+ StyledText st= fTextViewer.getTextWidget();
+ if (st != null && !st.isDisposed())
+ shell= st.getShell();
+ }
+ if (Display.getCurrent() != null)
+ MessageDialog.openError(shell, title, ex.getLocalizedMessage());
+ else {
+ Display display;
+ final Shell finalShell= shell;
+ if (finalShell != null)
+ display= finalShell.getDisplay();
+ else
+ display= Display.getDefault();
+ display.syncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openError(finalShell, title, ex.getLocalizedMessage());
+ }
+ });
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#setMaximalUndoLevel(int)
+ */
+ public void setMaximalUndoLevel(int undoLevel) {
+ fUndoLevel= Math.max(0, undoLevel);
+ if (isConnected()) {
+ fDocumentUndoManager.setUndoLimit(fUndoLevel);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#connect(org.eclipse.jface.text.ITextViewer)
+ */
+ public void connect(ITextViewer textViewer) {
+ if (fTextViewer == null && textViewer != null) {
+ fTextViewer= textViewer;
+ addListeners();
+ }
+ IDocument doc = fTextViewer.getDocument();
+ if (doc instanceof IDocumentExtension5) {
+ fDocumentUndoManager= ((IDocumentExtension5)doc).getUndoManager();
+ fDocumentUndoManager.connect(this);
+ setMaximalUndoLevel(fUndoLevel);
+ fDocumentUndoListener= new DocumentUndoListener();
+ fDocumentUndoManager.addDocumentUndoListener(fDocumentUndoListener);
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#disconnect()
+ */
+ public void disconnect() {
+ if (fTextViewer != null) {
+ removeListeners();
+ fTextViewer= null;
+ if (fDocumentUndoManager != null) {
+ fDocumentUndoManager.disconnect(this);
+ fDocumentUndoManager.removeDocumentUndoListener(fDocumentUndoListener);
+ fDocumentUndoManager= null;
+ fDocumentUndoListener= null;
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#reset()
+ */
+ public void reset() {
+ /*
+ * Disconnected and reconnecting will only initialize the history
+ * if there are no other clients tracking the undo history.
+ */
+ if (isConnected()) {
+ fDocumentUndoManager.disconnect(this);
+ fDocumentUndoManager.connect(this);
+ }
+
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#redoable()
+ */
+ public boolean redoable() {
+ if (isConnected())
+ return OperationHistoryFactory.getOperationHistory().canRedo(fDocumentUndoManager.getUndoContext());
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#undoable()
+ */
+ public boolean undoable() {
+ if (isConnected())
+ return OperationHistoryFactory.getOperationHistory().canUndo(getUndoContext());
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#redo()
+ */
+ public void redo() {
+ if (isConnected() && redoable()) {
+ try {
+ OperationHistoryFactory.getOperationHistory().redo(getUndoContext(), null, null);
+ } catch (ExecutionException ex) {
+ openErrorDialog(JFaceTextMessages.getString("DefaultUndoManager.error.redoFailed.title"), ex); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManager#undo()
+ */
+ public void undo() {
+ if (isConnected() && undoable()) {
+ try {
+ OperationHistoryFactory.getOperationHistory().undo(getUndoContext(), null, null);
+ } catch (ExecutionException ex) {
+ openErrorDialog(JFaceTextMessages.getString("DefaultUndoManager.error.undoFailed.title"), ex); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Selects and reveals the specified range.
+ *
+ * @param offset the offset of the range
+ * @param length the length of the range
+ * @since 3.0
+ */
+ protected void selectAndReveal(int offset, int length) {
+ if (fTextViewer instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer;
+ extension.exposeModelRange(new Region(offset, length));
+ } else if (!fTextViewer.overlapsWithVisibleRegion(offset, length))
+ fTextViewer.resetVisibleRegion();
+
+ fTextViewer.setSelectedRange(offset, length);
+ fTextViewer.revealRange(offset, length);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IUndoManagerExtension#getUndoContext()
+ * @since 3.1
+ */
+ public IUndoContext getUndoContext() {
+ if (isConnected()) {
+ return fDocumentUndoManager.getUndoContext();
+ }
+ return null;
+ }
+
+}