/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.antlr.works.editor.grammar.semantics;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Position;
import javax.swing.text.StyledDocument;
import org.antlr.netbeans.editor.text.DocumentSnapshot;
import org.antlr.netbeans.editor.text.SnapshotPosition;
import org.antlr.netbeans.editor.text.TrackingPosition;
import org.antlr.netbeans.editor.text.VersionedDocument;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.editor.errorstripe.privatespi.Mark;
import org.netbeans.modules.editor.errorstripe.privatespi.MarkProvider;
import org.netbeans.modules.editor.errorstripe.privatespi.Status;
import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
/**
*
* @author Sam Harwell
*/
public class MarkOccurrencesMarkProvider extends MarkProvider {
private final Object lock = new Object();
@NonNull
private List<Mark> occurrences;
public MarkOccurrencesMarkProvider() {
this.occurrences = Collections.emptyList();
}
@Override
public List<Mark> getMarks() {
synchronized (lock) {
return occurrences;
}
}
public void setOccurrences(Collection<Mark> marks) {
List<Mark> old;
List<Mark> nue;
synchronized (lock) {
old = occurrences;
occurrences = new ArrayList<>(marks);
nue = occurrences;
}
//#85919: fire outside the lock:
firePropertyChange(PROP_MARKS, old, nue);
}
public static Collection<Mark> createMarks(final VersionedDocument document, final Collection<SnapshotPosition> bag, final Color color, final String tooltip) {
final Document doc = document.getDocument();
if (doc == null) {
return Collections.emptyList();
}
final List<Mark> result = new LinkedList<>();
doc.render(new Runnable() {
@Override
public void run() {
DocumentSnapshot currentSnapshot = document.getCurrentSnapshot();
for (SnapshotPosition position : bag) {
try {
SnapshotPosition translatedPosition = position;
if (!position.getSnapshot().equals(currentSnapshot)) {
TrackingPosition trackingPosition = position.getSnapshot().createTrackingPosition(position.getOffset(), TrackingPosition.Bias.Forward);
translatedPosition = trackingPosition.getPosition(currentSnapshot);
}
result.add(new MarkImpl(doc, doc.createPosition(translatedPosition.getOffset()), color, tooltip));
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
}
}
});
return result;
}
private static class MarkImpl implements Mark {
private final Document doc;
private final Position startOffset;
private final Color color;
private final String tooltip;
public MarkImpl(Document doc, Position startOffset, Color color, String tooltip) {
this.doc = doc;
this.startOffset = startOffset;
this.color = color;
this.tooltip = tooltip;
}
@Override
public int getType() {
return TYPE_ERROR_LIKE;
}
@Override
public Status getStatus() {
// needs to be STATUS_WARNING or marks will be hidden by warnings in the error stripe
return Status.STATUS_WARNING;
}
@Override
public int getPriority() {
// high priority
return 0;
}
@Override
public Color getEnhancedColor() {
return color;
}
@Override
public int[] getAssignedLines() {
int line = NbDocument.findLineNumber((StyledDocument) doc, startOffset.getOffset());
return new int[] {line, line};
}
@Override
public String getShortDescription() {
return tooltip;
}
}
}