package org.netbeans.freemarker.highlight;
import freemarker.core.FMParserConstants;
import java.awt.Color;
import java.lang.ref.WeakReference;
import javax.swing.JEditorPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyleConstants;
import org.netbeans.api.editor.settings.AttributesUtilities;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.modules.editor.NbEditorUtilities;
import org.netbeans.spi.editor.highlighting.support.OffsetsBag;
import org.openide.cookies.EditorCookie;
import org.openide.loaders.DataObject;
import org.openide.util.RequestProcessor;
/**
*
* @author rostanek
*/
public class FTLHighlighter implements CaretListener {
private static final AttributeSet defaultColors =
AttributesUtilities.createImmutable(StyleConstants.Background,
new Color(236, 235, 163));
private final OffsetsBag bag;
private JTextComponent comp;
private final WeakReference<Document> weakDoc;
private final RequestProcessor rp;
private final static int REFRESH_DELAY = 100;
private RequestProcessor.Task lastRefreshTask;
public FTLHighlighter(Document doc) {
rp = new RequestProcessor(FTLHighlighter.class);
bag = new OffsetsBag(doc);
weakDoc = new WeakReference<Document>(doc);
DataObject dobj = NbEditorUtilities.getDataObject(weakDoc.get());
if (dobj != null) {
EditorCookie pane = dobj.getLookup().lookup(EditorCookie.class);
JEditorPane[] panes = pane.getOpenedPanes();
if (panes != null && panes.length > 0) {
comp = panes[0];
comp.addCaretListener(this);
}
}
}
@Override
public void caretUpdate(CaretEvent e) {
bag.clear();
setupAutoRefresh();
}
public void setupAutoRefresh() {
if (lastRefreshTask == null) {
lastRefreshTask = rp.create(new Runnable() {
@Override
public void run() {
Document doc = weakDoc.get();
if (doc != null) {
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).readLock();
}
try {
TokenHierarchy th = TokenHierarchy.get(doc);
TokenSequence ts = th.tokenSequence();
ts.move(comp.getCaretPosition());
ts.moveNext();
Token token = ts.token();
if (token.id().ordinal() == FMParserConstants.ID) {
String text = token.text().toString();
ts.moveStart();
while (ts.moveNext()) {
token = ts.token();
if (token.id().ordinal() == FMParserConstants.ID && token.length() == text.length()) {
if (token.text().toString().equals(text)) {
bag.addHighlight(ts.offset(), ts.offset() + token.length(), defaultColors);
}
}
}
}
} finally {
if (doc instanceof AbstractDocument) {
((AbstractDocument) doc).readUnlock();
}
}
}
}
});
}
lastRefreshTask.schedule(REFRESH_DELAY);
}
public OffsetsBag getHighlightsBag() {
return bag;
}
}