
If not, will it be in the near future?
Best Regards,
Gustavo Guerra
Best Regards,
Gustavo Guerra
namespace StatNeth.Blaise.IDE.SourceEditorWPF.Language {
/// <summary>
/// Bracket Tagger tags matching brackets and IF/ENDIF tokens
/// </summary>
public class BracketTagger : TaggerBase<IClassificationTag> {
private IToken selectedToken = null; // token selected by user
private int matchingTokenId = -1; // matching token to look for
private List<int> hoppingNodes = null; // tokens part of the bracket combination (e.g ELSE for a IF token)
private bool scanUpwards = true;
private IEditorView view;
private static List<int> IF_Nodes = new List<int>(); // hopping nodes for the IF token
private static IClassificationType bracketClassificationType = new ClassificationType("BracketHighlight", "Bracket Highlight");
/// <summary>
/// Initializes the <c>BracketTagger</c> class.
/// </summary>
static BracketTagger() {
SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(0x70, 0xC0, 0xC0, 0xC0));
AmbientHighlightingStyleRegistry.Instance.Register(bracketClassificationType, new HighlightingStyle(null, brush));
IF_Nodes.Add(Mediator.K_ELSEIF);
IF_Nodes.Add(Mediator.K_ELSE);
}
/// <summary>
/// Initializes a new instance of the <c>WordHighlightTagger</c> class.
/// </summary>
/// <param name="view">The view to which this manager is attached.</param>
public BracketTagger(IEditorView view)
: base("CustomBracketTagger",
new Ordering[] { new Ordering(TaggerKeys.Token, OrderPlacement.Before) }, view.SyntaxEditor.Document) {
// Initialize
this.view = view;
this.view.SelectionChanged += new EventHandler<EditorViewSelectionEventArgs>(OnViewSelectionChanged);
// Update current word
this.UpdateCurrentBracket();
}
/// <summary>
/// Occurs when the view's selection is changed.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="EditorViewSelectionEventArgs"/> that contains data related to this event.</param>
private void OnViewSelectionChanged(object sender, EditorViewSelectionEventArgs e) {
if (view == null)
return;
// Update
this.UpdateCurrentBracket();
}
private void UpdateCurrentBracket() {
// reset
selectedToken = null;
matchingTokenId = -1;
hoppingNodes = null;
if ((view == null) || (view.Selection == null))
return;
TextRange tr = view.GetCurrentWordTextRange();
if (tr.IsDeleted)
return;
selectedToken = view.CurrentSnapshot.GetReader(tr.StartOffset).Token;
if (selectedToken == null || selectedToken.TextRange == null || selectedToken.TextRange.IsDeleted) {
selectedToken = null;
return;
}
switch (selectedToken.Id) {
case Mediator.OpenParenthesis :
matchingTokenId = Mediator.CloseParenthesis;
scanUpwards = false;
break;
case Mediator.CloseParenthesis:
matchingTokenId = Mediator.OpenParenthesis;
scanUpwards = true;
break;
case Mediator.OpenSquareBrace:
matchingTokenId = Mediator.CloseSquareBrace;
scanUpwards = false;
break;
case Mediator.CloseSquareBrace:
matchingTokenId = Mediator.OpenSquareBrace;
scanUpwards = true;
break;
case Mediator.K_IF:
matchingTokenId = Mediator.K_ENDIF;
hoppingNodes = IF_Nodes;
scanUpwards = false;
break;
case Mediator.K_ENDIF:
matchingTokenId = Mediator.K_IF;
hoppingNodes = IF_Nodes;
scanUpwards = true;
break;
case Mediator.K_DO:
matchingTokenId = Mediator.K_ENDDO;
scanUpwards = false;
break;
case Mediator.K_ENDDO:
matchingTokenId = Mediator.K_DO;
scanUpwards = true;
break;
default:
selectedToken = null;
return;
}
// Notify that tags changed
this.OnTagsChanged(new TagsChangedEventArgs(new TextSnapshotRange(view.SyntaxEditor.Document.CurrentSnapshot, view.SyntaxEditor.Document.CurrentSnapshot.TextRange)));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC PROCEDURES
/////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Returns the tag ranges that intersect with the specified normalized snapshot ranges.
/// </summary>
/// <param name="snapshotRanges">The collection of normalized snapshot ranges.</param>
/// <param name="parameter">An optional parameter that provides contextual information about the tag request.</param>
/// <returns>The tag ranges that intersect with the specified normalized snapshot ranges.</returns>
public override IEnumerable<TagSnapshotRange<IClassificationTag>> GetTags(NormalizedTextSnapshotRangeCollection snapshotRanges, object parameter) {
if (selectedToken == null)
yield break;
// Loop through the requested snapshot ranges...
foreach (TextSnapshotRange snapshotRange in snapshotRanges) {
// If the snapshot range is not zero-length...
if (!snapshotRange.IsZeroLength) {
ITextSnapshotReader reader = null;
List<TextRange> hops = new List<TextRange>();
int stackSize = 0;
// get reader for search text
if (scanUpwards) {
reader = snapshotRange.Snapshot.GetReader(0);
if (reader != null) {
reader.Offset = selectedToken.StartOffset - 1;
}
} else {
reader = snapshotRange.Snapshot.GetReader(selectedToken.TextRange.LastOffset);
}
// start scanning
while (reader != null && reader.Token != null &&
( (scanUpwards && !reader.IsAtSnapshotStart) ||
(!scanUpwards && !reader.IsAtSnapshotEnd))) {
if (selectedToken.Id == reader.Token.Id) {
stackSize++;
} else if (stackSize == 0 && hoppingNodes != null && hoppingNodes.Contains(reader.Token.Id)) {
hops.Add(reader.Token.TextRange);
} else if (matchingTokenId == reader.Token.Id) {
if (stackSize > 0)
stackSize--;
else {
// mark selected token
yield return CreateTag(snapshotRange.Snapshot, selectedToken.TextRange);
// mark matching token
yield return CreateTag(snapshotRange.Snapshot, reader.Token.TextRange);
// mark hops
foreach (TextRange tr in hops) {
yield return CreateTag(snapshotRange.Snapshot, tr);
}
yield break;
}
}
if (scanUpwards) {
reader.GoToPreviousToken();
} else {
reader.GoToNextToken();
}
} // while
}
}
}
/// <summary>
/// Create a standard BracketTag
/// </summary>
/// <param name="snapshot"></param>
/// <param name="textRange"></param>
/// <returns></returns>
private static TagSnapshotRange<IClassificationTag> CreateTag(ITextSnapshot snapshot, TextRange textRange) {
return new TagSnapshotRange<IClassificationTag>(
new TextSnapshotRange(snapshot, textRange),
new ClassificationTag(bracketClassificationType)
);
}
/// <summary>
/// Occurs when the manager is closed and detached from the view.
/// </summary>
/// <remarks>
/// The default implementation of this method does nothing.
/// Overrides should release any event handlers set up in the manager's constructor.
/// </remarks>
protected override void OnClosed() {
// Detach from the view
if (view != null) {
view.SelectionChanged -= new EventHandler<EditorViewSelectionEventArgs>(OnViewSelectionChanged);
view = null;
}
// Call the base method
base.OnClosed();
}
}
}
We're happy to announce that delimiter highlighting has been added as a feature in the upcoming 2012.2 versions of SyntaxEditor. More detail is here:
http://blog.actiprosoftware.com/post.aspx?id=f0d37707-b41e-4f62-aca6-f92be80fba0e
Please log in to a validated account to post comments.