Click here to Skip to main content
12,819,402 members (33,902 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


39 bookmarked
Posted 6 Feb 2011

A WPF TikZ Editor (TikzEdt)

, , 6 Feb 2011 GPL3
Rate this:
Please Sign up or sign in to vote.
A combined text/WYSIWYG editor for the TikZ vector graphics language.


TikZ/PGF is a pair of widely used languages for creating vector graphics, in particular in Latex documents. There are a couple of editors assisting in the creation of TikZ code. However, mostly one has the choice between a text editor with preview, with no WYSIWYG capabilities, and a true WYSIWYG editor with a TikZ export function, without direct code access. Combining both direct code editing and WYSIWYG features is quite involved, since it requires a parser and interpreter that "understands" the TikZ code so that it can be rendered and edited in a WYSIWYG manner. We recently wrote such an editor, TikzEdt. This article describes the main programming challenges we faced, and design decisions we made to overcome them. Furthermore, there are some components of our program that can be reused for similar applications.

The latest version of the code and some further documentation can be found here.

For space reasons, we do not document TikzEdt's source code in full here. Instead, we will mostly restrict ourselves to describing the design decisions we made in human language and give only occasional code samples.


This article should be accessible to an audience acquainted with C#. However, the reader will benefit by knowing the essentials of LaTeX and TikZ/PGF programming, as well as of the Antlr parser generator to understand examples.

What TikzEdt does

Before we begin, let us briefly se what the editor does by looking at the above screenshot. On the left, there is a text box in which the user can freely type and edit LaTeX/TikZ code. On the right, there is a preview of the compiled TikZ picture, i.e., of the PDF produced by the LaTeX compiler when fed with the code on the left. On top of the preview, there is an overlay displayed (red X's). The user can edit this overlay in a WYSIWYG manner, for example, drag and drop a red X with the mouse. When (s)he does so, the TikZ-code in the textbox on the left is updated accordingly, and again compiled, so that the preview displayed on the right changes.

The text editor

The text editor (left half of screenshot) is based on the AvalonEdit component. It features syntax highlighting and basic code completion. AvalonEdit is described in detail in this CodeProject article. We added the following features:

A Find/Replace dialog

It incorporates the standard functions of Find/Replace dialogs.

Customizable code completions

The code completions are stored in an external XML file (CodeCompletions.xml). Each code completion belongs to a certain Environment, characterized by a start and an end tag, which can be specified as a Regular Expression in CodeCompletions.xml. The class CodeCompleter is used to read the XML file and fill the AvalonEdit CompletionWindow with the appropriate completions. The code for displaying the completions at the end looks as follows:

private void ShowCodeCompletionsCommandHandler(object sender, ExecutedRoutedEventArgs e)
    // Open code completion window
    completionWindow = new CompletionWindow(txtCode.TextArea);
    IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
    codeCompleter.GetCompletions(txtCode.Document, txtCode.CaretOffset, data);



Remark: We would like to make the Find/Replace dialog and CodeCompleter available as reusable libraries. However, for time reasons, we will need some help with more rigorous testing and maintenance. If you are interested, please contact one of the authors.

The snippet library

TikzEdt comes with a configurable snippet library. Its functionality is more or less standard, and not worth describing, except for one point: each snippet comes with a thumbnail image, which is compiled directly from LaTeX/TikZ code. Hence the user inserting a custom snippet does not have to produce a separate image file to display, but just has to insert some sample code, which is compiled to produce the thumbnail image.

The TikZ Parser

The technical heart of TikzEdt is the TikZ parser. The following issues had to be taken into account:

  • LaTeX/TikZ is not a very "clean" language, in particular it is ambiguous and not LL*.
  • We do not want to re-implement the full TikZ language, but only parts that are relevant for WYSIWYG editing. Hence the parser should be fault tolerant, i.e., also accept language constructions that it cannot "understand".
  • We do not have first hand specifications of TikZ. So part of the specification had to be reverse engineered.

To build the parser, we used the Antlr parser generator. The resulting parser produces from the TikZ code an abstract syntax tree (AST), representing only that portion of the TikZ file TikzEdt can understand. The AST is, in a second step, translated into a Tikz_ParseTree, which contains custom nodes for each type of TikZ object. For example, here is the C# class representing a TikZ node object:

public class Tikz_Node : Tikz_XYItem
    public static Tikz_Node FromCommonTree(CommonTree t, 
                            CommonTokenStream tokens)
    public void SetName(string tname)
    public override bool GetAbsPos(out Point ret, bool OnlyOffset = false) 
    public override void SetAbsPos(Point p)

Here, the static method FromCommonTree() is used to generate a Tikz_Node instance from an abstract AST node, which is passed as the argument t. The method GetAbsPos() returns the coordinates of the node.

The interpreter and coordinate computations

TikZ/PGF features an extensive system of coordinate transformations, and ways to specify relative coordinates or polar coordinates. For example, the following TikZ code produces a rotated and stretched rectangle:

\draw[rotate=30, xscale=3] (1,1) rectangle (3,3);

In order to accurately understand the position of nodes, those coordinate transformations have to be parsed and represented in TikzEdt. If the position of some object is queried, the correct coordinate transformations have to be applied to the raw coordinates parsed from the TikZ code (e.g., (1,1) in the example above). This is essentially implemented in the method GetCurrentTransformAt() in the nodes of the Tikz_ParseTree.

public bool GetCurrentTransformAt(TikzParseItem childtpi, out TikzMatrix M)
    if (parent != null)
        if (!parent.GetCurrentTransformAt(this, out M))
            return false;
        M = new TikzMatrix(); // identity matrix

    foreach (TikzParseItem tpi in Children)
        if (tpi == childtpi && childtpi != null)
        else if (tpi is Tikz_Options)
            TikzMatrix MM;
            if ((tpi as Tikz_Options).GetTransform(out MM))
                M = M * MM;
                return false;
    return true;

The method accepts some item in the parse tree and computes the current transform at this item's position. Afterwards, the raw coordinate, e.g., (1,1), can be transformed using TikzMatrix.Transform().

Real time PDF preview

TikzEdt does not have a TikZ rendering engine. The preview displayed in the WYSIWYG editor is the compiled PDFLaTeX output. Such an approach is only feasible if the compilation and display can happen very fast so as to not introduce significant delays between the user WYSIWYG-editing the overlay, and the preview following the change. We speed up PDFLaTeX compilation by using precompiled headers. Furthermore, to display the PDF, we use PDFLibNet wrapping the Xpdf/muPDF libraries, which is very fast. In effect, for small TikZ files, there is very little "lag" in the WYSIWYG editor.

Determining the bounding box

There is, as we know, no direct way to read off the bounding box of a TikZ picture from the compiled .pdf or LaTeX .aux files. However, we need this bounding box in order to correctly align the displayed overlay for WYSIWYG editing with the underlying PDF preview. What we do to determine the bounding box is that we write the following piece of code into the TeX file, to read out the bounding box and write it to a separate text file during LaTeX compilation.

    \p1=(current bounding box.south west),
    \p2=(current bounding box.north east)
  node[inner sep=0pt,outer sep=0pt,minimum size=0pt,line width=0pt,
       text width=0pt,text height=0pt,draw=white] at (current bounding box) {

The overlay and WYSIWYG functionality

To allow for WYSIWYG editing, an overlay is displayed on top of the PDF preview. For example, for the following piece of TikZ code:

\draw(-4,3) .. controls (-3,5) and (-1,6) .. (-1,3);
\draw (1,5) rectangle (4,3);
\draw(6,3) -- (9,5);

the raw output and overlay look like this:

One sees that overlay items are displayed for editing of the Bezier control points, the various coordinates present, and for the TikZ scope. The user can drag and drop the overlay items with the mouse, as in any WYSIWYG editor, and the TikZ source code is updated appropriately.

PdfOverlay class and display tree

All WYSIWYG functionality is implemented in the class PdfOverlay. Internally, this class translates the Tikz_Parsetree into another tree structure, a display tree (thus following the standard Model View pattern). For example, here is part of the definition of the class representing a coordinate in the display tree:

public class OverlayNode : OverlayShape
    public Tikz_XYItem tikzitem;
    public override TikzParseItem item { get { return tikzitem; } }

    public delegate void PositionChangedHandler(OverlayNode sender);
    public event PositionChangedHandler PositionChanged;

    public override bool AdjustPosition(double Resolution)

The field tikzitem holds the item in the Tikz_ParseTree this node of the display tree represents. The method AdjustPosition() is called to align the position of the OverlayNode on the screen with the position encoded in the underlying tikzitem.

Coordinate systems and rasterizer

The user usually likes to align multiple objects. For this reason, the coordinates of objects moved with the mouse should be rasterized. This is done in TikzEdt by the rasterControl class, which also displays a visual raster on screen. This class is a little more complicated than one might think as it has to support coordinate transformations and polar coordinates. For example, here is an image of a rotated, anisotropically scaled polar coordinate raster:

The underlying TikZ code in this case is this:

  \draw[rotate=30, xscale=1, yscale=4] (0,0)--(90:2)--+(180:5);

Extensible tool system

The picture can be edited in a WYSIWYG manner using multiple tools. We wanted the tool system to be as modular as possible, allowing for later additions of tools, or improvements on existing tools, without worrying about the implementation details of the rest of the program. Each tool is contained in a separate class, deriving from the OverlayTool base class. The access to the TikZ picture and user interface is granted through the OverlayInterface interface.

class OverlayTool
    /// <span class="code-SummaryComment"><summary>

Final remarks, and to-dos

We sketched here a combined text/WYSIWYG editor for vector graphics. We are not aware of any similar project within the Open Source community. At present, TikzEdt is still in development, and numerous features are left on the authors' wish list. At present, all help is welcome, be it in testing or coding, or just comments on our work. (Just contact the authors if you are interested to become a contributor.)


Our work would not have been possible without building on previous efforts by the community. In particular, we use the following components:


This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


About the Authors

Thomas Willwacher
United States United States
No Biography provided

Julian Ohrt
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

BugError while running Pin
Member 193282618-Jul-11 16:21
memberMember 193282618-Jul-11 16:21 
GeneralRe: Error while running Pin
Julian Ohrt18-Jul-11 21:08
memberJulian Ohrt18-Jul-11 21:08 
GeneralTheSnippets.xml is missing Pin
Member 47220157-Feb-11 6:31
memberMember 47220157-Feb-11 6:31 
GeneralRe: TheSnippets.xml is missing Pin
Julian Ohrt8-Feb-11 1:48
memberJulian Ohrt8-Feb-11 1:48 
GeneralRe: TheSnippets.xml is missing Pin
Thomas Willwacher8-Feb-11 5:16
memberThomas Willwacher8-Feb-11 5:16 
GeneralRe: TheSnippets.xml is missing Pin
Member 47220158-Feb-11 9:40
memberMember 47220158-Feb-11 9:40 
GeneralRe: TheSnippets.xml is missing Pin
Member 47220158-Feb-11 9:36
memberMember 47220158-Feb-11 9:36 
GeneralSlick Pin
Sacha Barber7-Feb-11 2:48
mvpSacha Barber7-Feb-11 2:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170308.1 | Last Updated 6 Feb 2011
Article Copyright 2011 by Thomas Willwacher, Julian Ohrt
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid