1) Moved net.sourceforge.phpeclipse.ui\src\net\sourceforge\phpdt back to net.sourcefo...
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / text / TypingRunDetector.java
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java
deleted file mode 100644 (file)
index aa63874..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.internal.ui.text;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
-
-//incastrix
-//import org.eclipse.jface.text.Assert;
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.jface.text.DocumentEvent;
-import org.eclipse.jface.text.ITextListener;
-import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.TextEvent;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-
-/**
- * When connected to a text viewer, a <code>TypingRunDetector</code> observes
- * <code>TypingRun</code> events. A typing run is a sequence of similar text
- * modifications, such as inserting or deleting single characters.
- * <p>
- * Listeners are informed about the start and end of a <code>TypingRun</code>.
- * </p>
- * 
- * @since 3.0
- */
-public class TypingRunDetector {
-       /*
-        * Implementation note: This class is independent of JDT and may be pulled
-        * up to jface.text if needed.
-        */
-
-       /** Debug flag. */
-       private static final boolean DEBUG = false;
-
-       /**
-        * Instances of this class abstract a text modification into a simple
-        * description. Typing runs consists of a sequence of one or more modifying
-        * changes of the same type. Every change records the type of change
-        * described by a text modification, and an offset it can be followed by
-        * another change of the same run.
-        */
-       private static final class Change {
-               private ChangeType fType;
-
-               private int fNextOffset;
-
-               /**
-                * Creates a new change of type <code>type</code>.
-                * 
-                * @param type
-                *            the <code>ChangeType</code> of the new change
-                * @param nextOffset
-                *            the offset of the next change in a typing run
-                */
-               public Change(ChangeType type, int nextOffset) {
-                       fType = type;
-                       fNextOffset = nextOffset;
-               }
-
-               /**
-                * Returns <code>true</code> if the receiver can extend the typing
-                * range the last change of which is described by <code>change</code>.
-                * 
-                * @param change
-                *            the last change in a typing run
-                * @return <code>true</code> if the receiver is a valid extension to
-                *         <code>change</code>,<code>false</code> otherwise
-                */
-               public boolean canFollow(Change change) {
-                       if (fType == TypingRun.NO_CHANGE)
-                               return true;
-                       else if (fType.equals(TypingRun.UNKNOWN))
-                               return false;
-                       if (fType.equals(change.fType)) {
-                               if (fType == TypingRun.DELETE)
-                                       return fNextOffset == change.fNextOffset - 1;
-                               else if (fType == TypingRun.INSERT)
-                                       return fNextOffset == change.fNextOffset + 1;
-                               else if (fType == TypingRun.OVERTYPE)
-                                       return fNextOffset == change.fNextOffset + 1;
-                               else if (fType == TypingRun.SELECTION)
-                                       return true;
-                       }
-                       return false;
-               }
-
-               /**
-                * Returns <code>true</code> if the receiver describes a text
-                * modification, <code>false</code> if it describes a focus /
-                * selection change.
-                * 
-                * @return <code>true</code> if the receiver is a text modification
-                */
-               public boolean isModification() {
-                       return fType.isModification();
-               }
-
-               /*
-                * @see java.lang.Object#toString()
-                */
-               public String toString() {
-                       return fType.toString() + "@" + fNextOffset; //$NON-NLS-1$
-               }
-
-               /**
-                * Returns the change type of this change.
-                * 
-                * @return the change type of this change
-                */
-               public ChangeType getType() {
-                       return fType;
-               }
-       }
-
-       /**
-        * Observes any events that modify the content of the document displayed in
-        * the editor. Since text events may start a new run, this listener is
-        * always registered if the detector is connected.
-        */
-       private class TextListener implements ITextListener {
-
-               /*
-                * @see org.eclipse.jface.text.ITextListener#textChanged(org.eclipse.jface.text.TextEvent)
-                */
-               public void textChanged(TextEvent event) {
-                       handleTextChanged(event);
-               }
-       }
-
-       /**
-        * Observes non-modifying events that will end a run, such as clicking into
-        * the editor, moving the caret, and the editor losing focus. These events
-        * can never start a run, therefore this listener is only registered if
-        * there is an ongoing run.
-        */
-       private class SelectionListener implements MouseListener, KeyListener,
-                       FocusListener {
-
-               /*
-                * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
-                */
-               public void focusGained(FocusEvent e) {
-                       handleSelectionChanged();
-               }
-
-               /*
-                * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
-                */
-               public void focusLost(FocusEvent e) {
-               }
-
-               /*
-                * @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)
-                               handleSelectionChanged();
-               }
-
-               /*
-                * @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:
-                       case SWT.END:
-                       case SWT.HOME:
-                       case SWT.PAGE_DOWN:
-                       case SWT.PAGE_UP:
-                               handleSelectionChanged();
-                               break;
-                       }
-               }
-       }
-
-       /** The listeners. */
-       private final Set fListeners = new HashSet();
-
-       /**
-        * The viewer we work upon. Set to <code>null</code> in
-        * <code>uninstall</code>.
-        */
-       private ITextViewer fViewer;
-
-       /** The text event listener. */
-       private final TextListener fTextListener = new TextListener();
-
-       /**
-        * The selection listener. Set to <code>null</code> when no run is active.
-        */
-       private SelectionListener fSelectionListener;
-
-       /* state variables */
-
-       /** The most recently observed change. Never <code>null</code>. */
-       private Change fLastChange;
-
-       /** The current run, or <code>null</code> if there is none. */
-       private TypingRun fRun;
-
-       /**
-        * Installs the receiver with a text viewer.
-        * 
-        * @param viewer
-        *            the viewer to install on
-        */
-       public void install(ITextViewer viewer) {
-               Assert.isLegal(viewer != null);
-               fViewer = viewer;
-               connect();
-       }
-
-       /**
-        * Initializes the state variables and registers any permanent listeners.
-        */
-       private void connect() {
-               if (fViewer != null) {
-                       fLastChange = new Change(TypingRun.UNKNOWN, -1);
-                       fRun = null;
-                       fSelectionListener = null;
-                       fViewer.addTextListener(fTextListener);
-               }
-       }
-
-       /**
-        * Uninstalls the receiver and removes all listeners. <code>install()</code>
-        * must be called for events to be generated.
-        */
-       public void uninstall() {
-               if (fViewer != null) {
-                       fListeners.clear();
-                       disconnect();
-                       fViewer = null;
-               }
-       }
-
-       /**
-        * Disconnects any registered listeners.
-        */
-       private void disconnect() {
-               fViewer.removeTextListener(fTextListener);
-               ensureSelectionListenerRemoved();
-       }
-
-       /**
-        * Adds a listener for <code>TypingRun</code> events. Repeatedly adding
-        * the same listener instance has no effect. Listeners may be added even if
-        * the receiver is neither connected nor installed.
-        * 
-        * @param listener
-        *            the listener add
-        */
-       public void addTypingRunListener(ITypingRunListener listener) {
-               Assert.isLegal(listener != null);
-               fListeners.add(listener);
-               if (fListeners.size() == 1)
-                       connect();
-       }
-
-       /**
-        * Removes the listener from this manager. If <code>listener</code> is not
-        * registered with the receiver, nothing happens.
-        * 
-        * @param listener
-        *            the listener to remove, or <code>null</code>
-        */
-       public void removeTypingRunListener(ITypingRunListener listener) {
-               fListeners.remove(listener);
-               if (fListeners.size() == 0)
-                       disconnect();
-       }
-
-       /**
-        * Handles an incoming text event.
-        * 
-        * @param event
-        *            the text event that describes the text modification
-        */
-       void handleTextChanged(TextEvent event) {
-               Change type = computeChange(event);
-               handleChange(type);
-       }
-
-       /**
-        * Computes the change abstraction given a text event.
-        * 
-        * @param event
-        *            the text event to analyze
-        * @return a change object describing the event
-        */
-       private Change computeChange(TextEvent event) {
-               DocumentEvent e = event.getDocumentEvent();
-               if (e == null)
-                       return new Change(TypingRun.NO_CHANGE, -1);
-
-               int start = e.getOffset();
-               int end = e.getOffset() + e.getLength();
-               String newText = e.getText();
-               if (newText == null)
-                       newText = new String();
-
-               if (start == end) {
-                       // no replace / delete / overwrite
-                       if (newText.length() == 1)
-                               return new Change(TypingRun.INSERT, end + 1);
-               } else if (start == end - 1) {
-                       if (newText.length() == 1)
-                               return new Change(TypingRun.OVERTYPE, end);
-                       if (newText.length() == 0)
-                               return new Change(TypingRun.DELETE, start);
-               }
-
-               return new Change(TypingRun.UNKNOWN, -1);
-       }
-
-       /**
-        * Handles an incoming selection event.
-        */
-       void handleSelectionChanged() {
-               handleChange(new Change(TypingRun.SELECTION, -1));
-       }
-
-       /**
-        * State machine. Changes state given the current state and the incoming
-        * change.
-        * 
-        * @param change
-        *            the incoming change
-        */
-       private void handleChange(Change change) {
-               if (change.getType() == TypingRun.NO_CHANGE)
-                       return;
-
-               if (DEBUG)
-                       System.err.println("Last change: " + fLastChange); //$NON-NLS-1$
-
-               if (!change.canFollow(fLastChange))
-                       endIfStarted(change);
-               fLastChange = change;
-               if (change.isModification())
-                       startOrContinue();
-
-               if (DEBUG)
-                       System.err.println("New change: " + change); //$NON-NLS-1$
-       }
-
-       /**
-        * Starts a new run if there is none and informs all listeners. If there
-        * already is a run, nothing happens.
-        */
-       private void startOrContinue() {
-               if (!hasRun()) {
-                       if (DEBUG)
-                               System.err.println("+Start run"); //$NON-NLS-1$
-                       fRun = new TypingRun(fLastChange.getType());
-                       ensureSelectionListenerAdded();
-                       fireRunBegun(fRun);
-               }
-       }
-
-       /**
-        * Returns <code>true</code> if there is an active run, <code>false</code>
-        * otherwise.
-        * 
-        * @return <code>true</code> if there is an active run, <code>false</code>
-        *         otherwise
-        */
-       private boolean hasRun() {
-               return fRun != null;
-       }
-
-       /**
-        * Ends any active run and informs all listeners. If there is none, nothing
-        * happens.
-        * 
-        * @param change
-        *            the change that triggered ending the active run
-        */
-       private void endIfStarted(Change change) {
-               if (hasRun()) {
-                       ensureSelectionListenerRemoved();
-                       if (DEBUG)
-                               System.err.println("-End run"); //$NON-NLS-1$
-                       fireRunEnded(fRun, change.getType());
-                       fRun = null;
-               }
-       }
-
-       /**
-        * Adds the selection listener to the text widget underlying the viewer, if
-        * not already done.
-        */
-       private void ensureSelectionListenerAdded() {
-               if (fSelectionListener == null) {
-                       fSelectionListener = new SelectionListener();
-                       StyledText textWidget = fViewer.getTextWidget();
-                       textWidget.addFocusListener(fSelectionListener);
-                       textWidget.addKeyListener(fSelectionListener);
-                       textWidget.addMouseListener(fSelectionListener);
-               }
-       }
-
-       /**
-        * If there is a selection listener, it is removed from the text widget
-        * underlying the viewer.
-        */
-       private void ensureSelectionListenerRemoved() {
-               if (fSelectionListener != null) {
-                       StyledText textWidget = fViewer.getTextWidget();
-                       textWidget.removeFocusListener(fSelectionListener);
-                       textWidget.removeKeyListener(fSelectionListener);
-                       textWidget.removeMouseListener(fSelectionListener);
-                       fSelectionListener = null;
-               }
-       }
-
-       /**
-        * Informs all listeners about a newly started <code>TypingRun</code>.
-        * 
-        * @param run
-        *            the new run
-        */
-       private void fireRunBegun(TypingRun run) {
-               List listeners = new ArrayList(fListeners);
-               for (Iterator it = listeners.iterator(); it.hasNext();) {
-                       ITypingRunListener listener = (ITypingRunListener) it.next();
-                       listener.typingRunStarted(fRun);
-               }
-       }
-
-       /**
-        * Informs all listeners about an ended <code>TypingRun</code>.
-        * 
-        * @param run
-        *            the previously active run
-        * @param reason
-        *            the type of change that caused the run to be ended
-        */
-       private void fireRunEnded(TypingRun run, ChangeType reason) {
-               List listeners = new ArrayList(fListeners);
-               for (Iterator it = listeners.iterator(); it.hasNext();) {
-                       ITypingRunListener listener = (ITypingRunListener) it.next();
-                       listener.typingRunEnded(fRun, reason);
-               }
-       }
-}