Tweets by @Actipro
Please take some time to learn more about us and our product offerings.
In this post I’d like to talk about an exciting new feature we’ve recently implemented in our SyntaxEditor for WPF codebase. Again, we haven’t released the product yet but there is a lot of interest in it so I’ve been trying to post on some of the things we’re working on. Everything discussed here is part of our next generation text/parsing model, which we eventually plan on making available to SyntaxEditor for WinForms too.
Be warned, this post gets a bit technical and is really meant for all the SyntaxEditor geeks out there! :)
A snapshot of a document provides an immutable read-only representation of the document at a certain time. The document always references the most current snapshot.
However say you start some time-consuming parsing on the most current snapshot, which we'll call snapshot 1. While the parsing is executing, more text changes in the document are made, bringing us to what we'll call snapshot 2. Then assume snapshot 1's parsing completes and returns an AST of the document. All the offsets for the AST are based on the text found in snapshot 1. Since snapshot 2 is the the most current snapshot, the offsets for the AST are most likely incorrect since they were not based on snapshot 2.
SyntaxEditor can translate offsets from one snapshot to another, taking any text changes into account. So if we wanted to jump directly to a class name, whose offset we know from the AST based on snapshot 1, we can translate the offset from snapshot 1 to the current snapshot (snapshot 2), and move the caret right to the translated offset.
Let’s walk through a QuickStart to show off this feature. In this QuickStart we have two SyntaxEditor controls. They both start off with the same document text, however they are separate documents. The upper editor is read-only and just shows the original contents of both editors. The lower editor can be modified.
The snapshot translation QuickStart
Both documents initially contain what is visible in the screenshot above in the upper editor, which is class declarations for MyClassA and MyClassB. In the lower editor we deleted the MyClassA declaration. Note the yellow line modification mark in the selection margin where our change was made.
Now back in the upper editor, we highlight the word MyClassB. Then we click the Translate Selection button. This takes any text changes that have been made since the original text was set, and translates the offsets of the upper editor’s selection to where the same offsets should now be in the lower editor.
The result is in the screenshot, where it highlights the lower editor’s MyClassB text. If there was not translation mechanism in place, the selection would have been incorrectly made somewhere in the comment area of the lower editor instead.
Here are two real-word examples of using this sort of feature.
The first is based on the overview at the start of this post. Say you have an AST that you generate based on one snapshot, and you use the resulting AST to render a TreeView containing the document outline. A common feature is to allow double-clicking on a TreeView node to jump right the related declaration in code. However considering that the TreeView is generally not in sync with the editor due to typing, etc., in the past it’s been a problem to ensure that we move the caret to the right spot. With the use of the SyntaxEditor snapshot translation feature, we can almost always go to the correct spot, the only exception being if a text change has been made over the target offset after the time that the TreeView’s snapshot was taken. However even in that case, the end result is still close.
The second example is find/replace results. Say you do a replace all operation on a document and list the replace locations in a ListBox. You could store the snapshot made after each replace in the related ListBox items. This would allow you to move directly to the replaced text on double-clicks, even after multiple edits have been made following the replace all operation.
I hope that by illustrating this example you can see the power that this mechanism provides. It will help ensure consistency for the end user’s point of view when making a lot of changes and dealing with find/replace results, AST-related operations, etc.
These sort of things are just some of the core enhancements we’re working on for the design of SyntaxEditor for WPF. More to come!