// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de // This code is made available under the terms of the Eclipse Public License, // version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html package net.sf.eclipsefp.haskell.ui.internal.editors.haskell.text; import net.sf.eclipsefp.haskell.ui.internal.preferences.editor.IEditorPreferenceNames; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextAttribute; import org.eclipse.jface.text.TextPresentation; import org.eclipse.jface.text.presentation.IPresentationDamager; import org.eclipse.jface.text.presentation.IPresentationRepairer; import org.eclipse.swt.custom.StyleRange; /** <p>simple damager and repairer that uses no scanner rules, but knows * how to handle multi-line text regions.</p> * * @author Leif Frenzel */ public class NonRuleBasedDamagerRepairer implements IPresentationDamager, IPresentationRepairer, IEditorPreferenceNames { /** The document this object works on */ protected IDocument document; private final boolean literate; private final ScannerManager man; public NonRuleBasedDamagerRepairer( final ScannerManager man,final boolean literate ) { this.man=man; this.literate = literate; } @Override public void setDocument( final IDocument document ) { this.document = document; } /** * Returns the end offset of the line that contains the specified offset or * if the offset is inside a line delimiter, the end offset of the next line. * * @param offset the offset whose line end offset must be computed * @return the line end offset for the given offset * @exception BadLocationException if offset is invalid in the * current document */ protected int endOfLineOf( final int offset ) throws BadLocationException { int result; IRegion info = document.getLineInformationOfOffset( offset ); if( offset <= info.getOffset() + info.getLength() ) { result = info.getOffset() + info.getLength(); } else { int line = document.getLineOfOffset( offset ); try { info = document.getLineInformation( line + 1 ); result = info.getOffset() + info.getLength(); } catch( BadLocationException x ) { result = document.getLength(); } } return result; } @Override public IRegion getDamageRegion( final ITypedRegion partition, final DocumentEvent event, final boolean documentPartitioningChanged ) { IRegion result = partition; if( !documentPartitioningChanged ) { try { IRegion info = document.getLineInformationOfOffset( event.getOffset() ); int start = Math.max( partition.getOffset(), info.getOffset() ); int end = event.getOffset() + getEventLength( event ); if( info.getOffset() <= end && end <= info.getOffset() + info.getLength() ) { // optimize the case of the same line end = info.getOffset() + info.getLength(); } else { end = endOfLineOf( end ); } end = Math.min( partition.getOffset() + partition.getLength(), end ); result = new Region( start, end - start ); } catch( BadLocationException x ) { // ignored } } return result; } @Override public void createPresentation( final TextPresentation presentation, final ITypedRegion region ) { int offset = region.getOffset(); int length = region.getLength(); addRange( presentation, offset, length, getDefaultAttribute() ); } /** * Adds style information to the given text presentation. * * @param presentation the text presentation to be extended * @param offset the offset of the range to be styled * @param length the length of the range to be styled * @param attribute the attribute describing the style of the range to * be styled */ protected void addRange( final TextPresentation presentation, final int offset, final int length, final TextAttribute attribute ) { if( attribute != null ) { presentation.addStyleRange( new StyleRange( offset, length, attribute.getForeground(), attribute.getBackground(), attribute.getStyle() ) ); } } // helping methods ////////////////// private TextAttribute getDefaultAttribute() { TextAttribute result; if( literate ) { result = man.getLiterateCommentAttribute(); } else { result = man.getCommentAttribute(); } return result; } private int getEventLength( final DocumentEvent event ) { return event.getText() == null ? event.getLength() : event.getText().length(); } }