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