org.eclipse.jface.text.TextViewerUndoManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.jface.text Show documentation
Show all versions of org.eclipse.jface.text Show documentation
This is org.eclipse.jface.text jar used by Scout SDK
The newest version!
/*******************************************************************************
* Copyright (c) 2006, 2008 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.text.undo.DocumentUndoEvent;
import org.eclipse.text.undo.DocumentUndoManager;
import org.eclipse.text.undo.DocumentUndoManagerRegistry;
import org.eclipse.text.undo.IDocumentUndoListener;
import org.eclipse.text.undo.IDocumentUndoManager;
import org.eclipse.jface.dialogs.MessageDialog;
/**
* Implementation of {@link org.eclipse.jface.text.IUndoManager} using the shared
* document undo manager.
*
* 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 ITextViewer
* @see ITextInputListener
* @see IDocumentUndoManager
* @see MouseListener
* @see KeyListener
* @see DocumentUndoManager
*
* @since 3.2
* @noextend This class is not intended to be subclassed by clients.
*/
public class TextViewerUndoManager implements IUndoManager, IUndoManagerExtension {
/**
* Internal listener to mouse and key events.
*/
private class KeyAndMouseListener implements MouseListener, KeyListener {
/*
* @see MouseListener#mouseDoubleClick
*/
@Override
public void mouseDoubleClick(MouseEvent e) {
}
/*
* If the right mouse button is pressed, the current editing command is closed
* @see MouseListener#mouseDown
*/
@Override
public void mouseDown(MouseEvent e) {
if (e.button == 1)
if (isConnected())
fDocumentUndoManager.commit();
}
/*
* @see MouseListener#mouseUp
*/
@Override
public void mouseUp(MouseEvent e) {
}
/*
* @see KeyListener#keyPressed
*/
@Override
public void keyReleased(KeyEvent e) {
}
/*
* On cursor keys, the current editing command is closed
* @see KeyListener#keyPressed
*/
@Override
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.
*/
private class TextInputListener implements ITextInputListener {
@Override
public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
disconnectDocumentUndoManager();
}
@Override
public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
connectDocumentUndoManager(newInput);
}
}
/**
* Internal document undo listener.
*/
private class DocumentUndoListener implements IDocumentUndoListener {
@Override
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() {
@Override
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() {
@Override
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);
}
// Reveal the change if this manager's viewer has the focus.
if (fTextViewer != null) {
StyledText widget= fTextViewer.getTextWidget();
if (widget != null && !widget.isDisposed() && (widget.isFocusControl()))// || fTextViewer.getTextWidget() == control))
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 that is active. */
private IDocument fDocument;
/** 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 TextViewerUndoManager(int undoLevel) {
fUndoLevel= undoLevel;
}
/**
* Returns whether this undo manager is connected to a text viewer.
*
* @return true
if connected, false
otherwise
*/
private boolean isConnected() {
return fTextViewer != null && fDocumentUndoManager != null;
}
/*
* @see IUndoManager#beginCompoundChange
*/
@Override
public void beginCompoundChange() {
if (isConnected()) {
fDocumentUndoManager.beginCompoundChange();
}
}
/*
* @see IUndoManager#endCompoundChange
*/
@Override
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
*/
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() {
@Override
public void run() {
MessageDialog.openError(finalShell, title, ex.getLocalizedMessage());
}
});
}
}
@Override
public void setMaximalUndoLevel(int undoLevel) {
fUndoLevel= Math.max(0, undoLevel);
if (isConnected()) {
fDocumentUndoManager.setMaximalUndoLevel(fUndoLevel);
}
}
@Override
public void connect(ITextViewer textViewer) {
if (fTextViewer == null && textViewer != null) {
fTextViewer= textViewer;
addListeners();
}
IDocument doc= fTextViewer.getDocument();
connectDocumentUndoManager(doc);
}
@Override
public void disconnect() {
if (fTextViewer != null) {
removeListeners();
fTextViewer= null;
}
disconnectDocumentUndoManager();
}
@Override
public void reset() {
if (isConnected())
fDocumentUndoManager.reset();
}
@Override
public boolean redoable() {
if (isConnected())
return fDocumentUndoManager.redoable();
return false;
}
@Override
public boolean undoable() {
if (isConnected())
return fDocumentUndoManager.undoable();
return false;
}
@Override
public void redo() {
if (isConnected()) {
try {
fDocumentUndoManager.redo();
} catch (ExecutionException ex) {
openErrorDialog(JFaceTextMessages.getString("DefaultUndoManager.error.redoFailed.title"), ex); //$NON-NLS-1$
}
}
}
@Override
public void undo() {
if (isConnected()) {
try {
fDocumentUndoManager.undo();
} 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
*/
private 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);
}
@Override
public IUndoContext getUndoContext() {
if (isConnected()) {
return fDocumentUndoManager.getUndoContext();
}
return null;
}
private void connectDocumentUndoManager(IDocument document) {
disconnectDocumentUndoManager();
if (document != null) {
fDocument= document;
DocumentUndoManagerRegistry.connect(fDocument);
fDocumentUndoManager= DocumentUndoManagerRegistry.getDocumentUndoManager(fDocument);
fDocumentUndoManager.connect(this);
setMaximalUndoLevel(fUndoLevel);
fDocumentUndoListener= new DocumentUndoListener();
fDocumentUndoManager.addDocumentUndoListener(fDocumentUndoListener);
}
}
private void disconnectDocumentUndoManager() {
if (fDocumentUndoManager != null) {
fDocumentUndoManager.disconnect(this);
DocumentUndoManagerRegistry.disconnect(fDocument);
fDocumentUndoManager.removeDocumentUndoListener(fDocumentUndoListener);
fDocumentUndoListener= null;
fDocumentUndoManager= null;
}
}
}