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