# Painters

## Content



Painters are a way of extending C1RichTextBox by displaying **UIElements** in the same canvas where **C1RichTextBox** displays text. This allows more general extensions than style overrides, but might be harder to use. Painters are used internally by **C1RichTextBox** to display the selection.

A painter is an implementation of the [IRichTextPainter](/componentone/api/wpf/online-richtextbox/dotnet-api/C1.WPF.RichTextBox/C1.WPF.RichTextBox.IRichTextPainter.html) interface. This interface has two methods, [IRichTextPainter.Paint](/componentone/api/wpf/online-richtextbox/dotnet-api/C1.WPF.RichTextBox/C1.WPF.RichTextBox.IRichTextPainter.Paint.html) and [IRichTextPainter.PaintInline](/componentone/api/wpf/online-richtextbox/dotnet-api/C1.WPF.RichTextBox/C1.WPF.RichTextBox.IRichTextPainter.PaintInline.html), which are called at different stages of **C1RichTextBox**'s painting pass. Each method receives a **C1PaintingContext** object that is used to check the viewport being painted, and has the methods that are used for painting custom **UIElements**.

**IRichTextPainter.Paint** is called each time the entire screen is repainted. Note that each time this method is called, all **UIElements** must be painted by calling **C1PaintingContext.Paint**, otherwise they will be removed. Passing the same **UIElement** each time is more efficient, as it is not removed from the visual tree.

**IRichTextPainter.PaintInline** is called for each [C1Line](/componentone/api/wpf/online-richtextbox/dotnet-api/C1.WPF.RichTextBox/C1.WPF.RichTextBox.C1Line.html) that is painted. This method allows finer control over the layer where custom **UIElements** are painted. For instance, it is possible to paint above the text background, but below the text itself. It has the same rule as **IRichTextPainter.Paint**. All **UIElements** must be painted by calling **C1PaintingContext.PaintInline**, otherwise they will be removed.

The **Annotations** sample uses painters to display sticky notes. Here is the implementation:

```vbnet
Class StickyPainter
    Implements IRichTextPainter
    Private _stickies As List(Of StickyNote)
    Public Sub New(stickies As List(Of StickyNote))
        _stickies = stickies
    End Sub
    Public Sub Paint(context As C1PaintingContext)
        For Each sticky As var In _stickies
            Dim rect = context.ViewManager.GetRectFromPosition(sticky.Range.Start)
            context.Paint(Math.Round(rect.X), Math.Round(rect.Bottom), False, sticky)
        Next
    End Sub
    Public Sub PaintInline(context As C1PaintingContext, line As C1Line)
    End Sub
    Public Event PainterChanged As EventHandler(Of RichTextPainterChangeEventArgs)
End Class
```

```csharp
class StickyPainter : IRichTextPainter
{
    List<StickyNote> _stickies;
    public StickyPainter(List<StickyNote> stickies)
    {
        _stickies = stickies;
    }
    public void Paint(C1PaintingContext context)
    {
        foreach (var sticky in _stickies)
        {
            var rect = context.ViewManager.GetRectFromPosition(sticky.Range.Start);
            context.Paint(Math.Round(rect.X), Math.Round(rect.Bottom), false, sticky);
        }
    }
    public void PaintInline(C1PaintingContext context, C1Line line)
    {
    }
    public event EventHandler<RichTextPainterChangeEventArgs> PainterChanged;
}
```

**StickyPainter** only uses the **C1PaintingContext.Paint** method. For each sticky note it just gets the coordinates inside document and then calls **C1PaintingContext.Paint**. Note that these are document coordinates; they are independent of paging, scrolling and zooming.