All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.text.TextViewerUndoManager Maven / Gradle / Ivy

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; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy