--- /dev/null
+package net.sourceforge.phpeclipse.phpeditor;
+
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+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.Control;
+
+public final class PaintManager implements KeyListener, MouseListener,
+ ISelectionChangedListener, ITextListener, ITextInputListener {
+
+ static class PaintPositionUpdater extends DefaultPositionUpdater {
+
+ /**
+ * Creates the position updater.
+ */
+ protected PaintPositionUpdater(String category) {
+ super(category);
+ }
+
+ /**
+ * If an insertion happens at a position's offset, the position is
+ * extended rather than shifted. Also, if something is added right
+ * behind the end of the position, the position is extended rather than
+ * kept stable.
+ */
+ protected void adaptToInsert() {
+
+ int myStart = fPosition.offset;
+ int myEnd = fPosition.offset + fPosition.length;
+ myEnd = Math.max(myStart, myEnd);
+
+ int yoursStart = fOffset;
+ int yoursEnd = fOffset + fReplaceLength;// - 1;
+ yoursEnd = Math.max(yoursStart, yoursEnd);
+
+ if (myEnd < yoursStart)
+ return;
+
+ if (myStart <= yoursStart)
+ fPosition.length += fReplaceLength;
+ else
+ fPosition.offset += fReplaceLength;
+ }
+ };
+
+ static class PositionManager implements IPositionManager {
+
+ private IDocument fDocument;
+
+ private IPositionUpdater fPositionUpdater;
+
+ private String fCategory;
+
+ public PositionManager() {
+ fCategory = getClass().getName() + hashCode();
+ fPositionUpdater = new PaintPositionUpdater(fCategory);
+ }
+
+ public void install(IDocument document) {
+ fDocument = document;
+ fDocument.addPositionCategory(fCategory);
+ fDocument.addPositionUpdater(fPositionUpdater);
+ }
+
+ public void dispose() {
+ uninstall(fDocument);
+ }
+
+ public void uninstall(IDocument document) {
+ if (document == fDocument && document != null) {
+ try {
+ fDocument.removePositionUpdater(fPositionUpdater);
+ fDocument.removePositionCategory(fCategory);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ }
+ fDocument = null;
+ }
+ }
+
+ /*
+ * @see IPositionManager#addManagedPosition(Position)
+ */
+ public void addManagedPosition(Position position) {
+ try {
+ fDocument.addPosition(fCategory, position);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ } catch (BadLocationException x) {
+ // should not happen
+ }
+ }
+
+ /*
+ * @see IPositionManager#removeManagedPosition(Position)
+ */
+ public void removeManagedPosition(Position position) {
+ try {
+ fDocument.removePosition(fCategory, position);
+ } catch (BadPositionCategoryException x) {
+ // should not happen
+ }
+ }
+ };
+
+ private List fPainters = new ArrayList(2);
+
+ private PositionManager fManager;
+
+ private ISourceViewer fSourceViewer;
+
+ private boolean fTextChanged = false;
+
+ private boolean fAutoRepeat = false;
+
+ public PaintManager(ISourceViewer sourceViewer) {
+ fSourceViewer = sourceViewer;
+ }
+
+ public void addPainter(IPainter painter) {
+ if (!fPainters.contains(painter)) {
+ fPainters.add(painter);
+ if (fPainters.size() == 1)
+ install();
+ painter.setPositionManager(fManager);
+ painter.paint(IPainter.INTERNAL);
+ }
+ }
+
+ public void removePainter(IPainter painter) {
+ if (fPainters.remove(painter))
+ painter.setPositionManager(null);
+ if (fPainters.size() == 0)
+ dispose();
+ }
+
+ private void install() {
+
+ fManager = new PositionManager();
+ fManager.install(fSourceViewer.getDocument());
+
+ fSourceViewer.addTextInputListener(this);
+
+ ISelectionProvider provider = fSourceViewer.getSelectionProvider();
+ provider.addSelectionChangedListener(this);
+
+ fSourceViewer.addTextListener(this);
+
+ StyledText text = fSourceViewer.getTextWidget();
+ text.addKeyListener(this);
+ text.addMouseListener(this);
+ }
+
+ public void dispose() {
+
+ if (fManager != null) {
+ fManager.dispose();
+ fManager = null;
+ }
+
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).dispose();
+ fPainters.clear();
+
+ fSourceViewer.removeTextInputListener(this);
+
+ ISelectionProvider provider = fSourceViewer.getSelectionProvider();
+ if (provider != null)
+ provider.removeSelectionChangedListener(this);
+
+ fSourceViewer.removeTextListener(this);
+
+ StyledText text = fSourceViewer.getTextWidget();
+ if (text != null && !text.isDisposed()) {
+ text.removeKeyListener(this);
+ text.removeMouseListener(this);
+ }
+ }
+
+ private void paint(int reason) {
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).paint(reason);
+ }
+
+ /*
+ * @see KeyListener#keyPressed(KeyEvent)
+ */
+ public void keyPressed(KeyEvent e) {
+ paint(IPainter.KEY_STROKE);
+ }
+
+ /*
+ * @see KeyListener#keyReleased(KeyEvent)
+ */
+ public void keyReleased(KeyEvent e) {
+ }
+
+ /*
+ * @see MouseListener#mouseDoubleClick(MouseEvent)
+ */
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ /*
+ * @see MouseListener#mouseDown(MouseEvent)
+ */
+ public void mouseDown(MouseEvent e) {
+ paint(IPainter.MOUSE_BUTTON);
+ }
+
+ /*
+ * @see MouseListener#mouseUp(MouseEvent)
+ */
+ public void mouseUp(MouseEvent e) {
+ }
+
+ /*
+ * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ paint(IPainter.SELECTION);
+ }
+
+ /*
+ * @see ITextListener#textChanged(TextEvent)
+ */
+ public void textChanged(TextEvent event) {
+
+ if (!event.getViewerRedrawState())
+ return;
+
+ fTextChanged = true;
+ Control control = fSourceViewer.getTextWidget();
+ if (control != null) {
+ control.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (fTextChanged && fSourceViewer != null)
+ paint(IPainter.TEXT_CHANGE);
+ }
+ });
+ }
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument,
+ * IDocument)
+ */
+ public void inputDocumentAboutToBeChanged(IDocument oldInput,
+ IDocument newInput) {
+ if (oldInput != null) {
+ for (Iterator e = fPainters.iterator(); e.hasNext();)
+ ((IPainter) e.next()).deactivate(false);
+ fManager.uninstall(oldInput);
+ }
+ }
+
+ /*
+ * @see ITextInputListener#inputDocumentChanged(IDocument, IDocument)
+ */
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ if (newInput != null) {
+ fManager.install(newInput);
+ paint(IPainter.TEXT_CHANGE);
+ }
+ }
+}