package net.sourceforge.phpeclipse.phpeditor; /* * (c) Copyright IBM Corp. 2000, 2001. * All Rights Reserved. */ import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; public final class BracketPainter implements IPainter, PaintListener { private PHPPairMatcher fMatcher = new PHPPairMatcher(new char[] { '{', '}', '(', ')', '[', ']' }); private Position fBracketPosition = new Position(0, 0); private int fAnchor; private boolean fIsActive = false; private ISourceViewer fSourceViewer; private StyledText fTextWidget; private Color fColor; private IPositionManager fPositionManager; public BracketPainter(ISourceViewer sourceViewer) { fSourceViewer = sourceViewer; fTextWidget = sourceViewer.getTextWidget(); } public void setHighlightColor(Color color) { fColor = color; } public void dispose() { if (fMatcher != null) { fMatcher.dispose(); fMatcher = null; } fColor = null; fTextWidget = null; } public void deactivate(boolean redraw) { if (fIsActive) { fIsActive = false; fTextWidget.removePaintListener(this); if (fPositionManager != null) fPositionManager.removeManagedPosition(fBracketPosition); if (redraw) handleDrawRequest(null); } } public void paintControl(PaintEvent event) { if (fTextWidget != null) handleDrawRequest(event.gc); } private void handleDrawRequest(GC gc) { if (fBracketPosition.isDeleted) return; int offset = fBracketPosition.getOffset(); int length = fBracketPosition.getLength(); if (length < 1) return; if (fSourceViewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) fSourceViewer; IRegion widgetRange = extension.modelRange2WidgetRange(new Region( offset, length)); if (widgetRange == null) return; offset = widgetRange.getOffset(); length = widgetRange.getLength(); } else { IRegion region = fSourceViewer.getVisibleRegion(); if (region.getOffset() > offset || region.getOffset() + region.getLength() < offset + length) return; offset -= region.getOffset(); } if (PHPPairMatcher.RIGHT == fAnchor) draw(gc, offset, 1); else draw(gc, offset + length - 1, 1); } private void draw(GC gc, int offset, int length) { if (gc != null) { Point left = fTextWidget.getLocationAtOffset(offset); Point right = fTextWidget.getLocationAtOffset(offset + length); gc.setForeground(fColor); gc.drawRectangle(left.x, left.y, right.x - left.x - 1, gc .getFontMetrics().getHeight() - 1); } else { fTextWidget.redrawRange(offset, length, true); } } /* * @see IPainter#paint(int) */ public void paint(int reason) { Point selection = fSourceViewer.getSelectedRange(); if (selection.y > 0) { deactivate(true); return; } IRegion pair = fMatcher.match(fSourceViewer.getDocument(), selection.x); if (pair == null) { deactivate(true); return; } if (fIsActive) { // only if different if (pair.getOffset() != fBracketPosition.getOffset() || pair.getLength() != fBracketPosition.getLength() || fMatcher.getAnchor() != fAnchor) { // remove old highlighting handleDrawRequest(null); // update position fBracketPosition.isDeleted = false; fBracketPosition.offset = pair.getOffset(); fBracketPosition.length = pair.getLength(); fAnchor = fMatcher.getAnchor(); // apply new highlighting handleDrawRequest(null); } } else { fIsActive = true; fBracketPosition.isDeleted = false; fBracketPosition.offset = pair.getOffset(); fBracketPosition.length = pair.getLength(); fAnchor = fMatcher.getAnchor(); fTextWidget.addPaintListener(this); fPositionManager.addManagedPosition(fBracketPosition); handleDrawRequest(null); } } /* * @see IPainter#setPositionManager(IPositionManager) */ public void setPositionManager(IPositionManager manager) { fPositionManager = manager; } }