/******************************************************************************* | |
* Copyright (c) 2005, 2007 ILOG and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Joel Cheuoua - Initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.jet.internal.editor.partition; | |
import org.eclipse.core.runtime.Assert; | |
import org.eclipse.jface.text.*; | |
import org.eclipse.jface.text.presentation.IPresentationDamager; | |
import org.eclipse.jface.text.presentation.IPresentationRepairer; | |
import org.eclipse.jface.text.rules.*; | |
import org.eclipse.swt.custom.StyleRange; | |
public class PartitionScannerBasedDamagerRepairer implements IPresentationDamager, IPresentationRepairer { | |
protected IDocument document; | |
protected IPartitionTokenScanner partitionScanner; | |
protected ITokenScannerProvider tokenScannerProvider; | |
protected TextAttribute defaultTextAttribute; | |
public PartitionScannerBasedDamagerRepairer(IPartitionTokenScanner scanner, ITokenScannerProvider provider) { | |
Assert.isNotNull(scanner); | |
Assert.isNotNull(provider); | |
partitionScanner = scanner; | |
tokenScannerProvider = provider; | |
defaultTextAttribute = new TextAttribute(null); | |
} | |
public void setDocument(IDocument document) { | |
this.document = document; | |
} | |
public void setPartitionScanner(IPartitionTokenScanner partitionScanner) { | |
this.partitionScanner = partitionScanner; | |
} | |
public void setTokenScannerProvider(ITokenScannerProvider provider) { | |
tokenScannerProvider = provider; | |
} | |
public IRegion getDamageRegion(ITypedRegion partition, DocumentEvent e, boolean documentPartitioningChanged) { | |
if (!documentPartitioningChanged) | |
return new Region(partition.getOffset(), partition.getLength()); | |
else | |
return partition; | |
} | |
public void createPresentation(TextPresentation presentation, ITypedRegion region) { | |
partitionScanner.setRange(document, region.getOffset(), region.getLength()); | |
String lastContentType = null; | |
int partitionScannerTokenLength = 0; | |
int partitionScannerTokenOffset = region.getOffset(); | |
do { | |
IToken partitionToken = partitionScanner.nextToken(); | |
if (partitionToken.isEOF()) { | |
if (lastContentType != null) { | |
ITokenScanner tokenScanner = tokenScannerProvider.getTokenScanner(lastContentType); | |
if (tokenScanner == null) | |
addRange(presentation, partitionScanner.getTokenOffset(), partitionScanner.getTokenLength(), | |
defaultTextAttribute); | |
else | |
applyTokenScanner(presentation, partitionScannerTokenLength, partitionScannerTokenOffset, tokenScanner); | |
} | |
break; | |
} | |
String contentType = getTokenContentType(partitionToken); | |
if (contentType == null) | |
contentType = IDocument.DEFAULT_CONTENT_TYPE; | |
if (contentType.equals(lastContentType)) { | |
partitionScannerTokenLength += partitionScanner.getTokenLength(); | |
} else { | |
if (lastContentType != null) { | |
ITokenScanner tokenScanner = tokenScannerProvider.getTokenScanner(lastContentType); | |
if (tokenScanner == null) | |
addRange(presentation, partitionScanner.getTokenOffset(), partitionScanner.getTokenLength(), | |
defaultTextAttribute); | |
else | |
applyTokenScanner(presentation, partitionScannerTokenLength, partitionScannerTokenOffset, tokenScanner); | |
} | |
lastContentType = contentType; | |
partitionScannerTokenOffset = partitionScanner.getTokenOffset(); | |
partitionScannerTokenLength = partitionScanner.getTokenLength(); | |
} | |
} while (true); | |
} | |
private void applyTokenScanner(TextPresentation presentation, int partitionScannerTokenLength, | |
int partitionScannerTokenOffset, ITokenScanner tokenScanner) { | |
int lastStart = partitionScannerTokenOffset; | |
int length = 0; | |
boolean firstToken = true; | |
IToken lastToken = Token.UNDEFINED; | |
TextAttribute lastAttribute = getTokenTextAttribute(lastToken); | |
tokenScanner.setRange(document, partitionScannerTokenOffset, partitionScannerTokenLength); | |
do { | |
IToken token = tokenScanner.nextToken(); | |
if (!token.isEOF()) { | |
TextAttribute attribute = getTokenTextAttribute(token); | |
if (lastAttribute != null && lastAttribute.equals(attribute)) { | |
length += tokenScanner.getTokenLength(); | |
firstToken = false; | |
} else { | |
if (!firstToken) | |
addRange(presentation, lastStart, length, lastAttribute); | |
firstToken = false; | |
lastToken = token; | |
lastAttribute = attribute; | |
lastStart = tokenScanner.getTokenOffset(); | |
length = tokenScanner.getTokenLength(); | |
} | |
} else { | |
addRange(presentation, lastStart, length, lastAttribute); | |
return; | |
} | |
} while (true); | |
} | |
protected String getTokenContentType(IToken token) { | |
Object data = token.getData(); | |
if (data instanceof String) | |
return (String) data; | |
else | |
return null; | |
} | |
protected TextAttribute getTokenTextAttribute(IToken token) { | |
Object data = token.getData(); | |
if (data instanceof TextAttribute) | |
return (TextAttribute) data; | |
else | |
return defaultTextAttribute; | |
} | |
protected void addRange(TextPresentation presentation, int offset, int length, TextAttribute attr) { | |
if (attr != null) { | |
int style = attr.getStyle(); | |
int fontStyle = style & 3; | |
StyleRange styleRange = new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), fontStyle); | |
styleRange.strikeout = (style & 0x20000000) != 0; | |
styleRange.underline = (style & 0x40000000) != 0; | |
styleRange.font = attr.getFont(); | |
presentation.addStyleRange(styleRange); | |
} | |
} | |
} |