Pinta's goal is to make writing an extension as easy as possible, and requiring as little infrastructure code as possible so you can focus on writing your code. Of course,
some infrastructure is required. The purpose of this guide is to walk you through setting up the code that all extensions need to be loaded by Pinta.
Step 1 - Create a New Assembly
In Visual Studio or MonoDevelop, create a new .NET 3.5 Class Library project.
Step 2 - Reference Asssemblies
In order to write an extension, you are going to need to reference two assemblies. These are:
- Mono.Addins.dll, which provides the machinery for extensions
- Pinta.Core.dll, which provides access to Pinta's API
These can be found alongside the Pinta executable.

There are several other assemblies that you'll probably also want to reference:
- gdk-sharp.dll, for writing Gtk#
- glib-sharp.dll, for writing Gtk#
- gtk-sharp.dll, for writing Gtk#
- Mono.Cairo.dll, for manipulating images
These are probably in your GAC.
Step 3 - Assembly Level Attributes
Pinta needs to know some basic information about your assembly so it can find it and show it in the extension manager dialog. Add the following assembly level attributes to your project, often in AssemblyInfo.cs:
[assembly: Addin ("MyExtension", "1.0", Category = "Other")]
[assembly: AddinName ("My First Extension")]
[assembly: AddinDescription ("This is a sample extension for Pinta.")]
[assembly: AddinDependency ("Pinta", "1.1")]- Addin takes a unique id for your extension, your extension version, and a category to help group your extension in the extension manager.
- AddinName takes the friendly name for your extension that you want the user to see.
- AddinDescription provides a description so users know what your extension does.
- AddinDependency lets the extension system know you require version 1.0 of Pinta.
These attributes all live in the Mono.Addins namespace.
Step 4 - IExtension Interface
In Pinta, all extensions implement the IExtension interface. This interface only has 2 members: Initialize and Uninitialize. Initialize is where you want to set up your extension.
Do not do your initialization in the constructor, as your extension may be instantiated even if the user has it disabled.
Additionally, you need to mark your extension class with the
Mono.Addins.Extension attribute to help Pinta find it.
A simple extension looks like this:
using System;
[Mono.Addins.Extension]
public class MyFirstExtension : Pinta.Core.IExtension
{
public void Initialize ()
{
}
public void Uninitialize ()
{
}
}We'll go ahead and add references to gtk-sharp.dll and friends so we can show a message box when your extension is initialized. You probably would never want to show a dialog in Initialize because it will hold up loading Pinta, but we'll do it here to illustrate what's going on.
public void Initialize ()
{
var dialog = new Gtk.MessageDialog (null, Gtk.DialogFlags.Modal,
Gtk.MessageType.Info, Gtk.ButtonsType.Ok, "MyFirstExtension Initialized!");
dialog.Run ();
dialog.Destroy ();
}Step 5 - Compile and Run Your Extension¶
That's all that is needed to create an empty extension. Compile your assembly and place it in the same directory as Pinta.exe. Fire up Pinta and your new extension should load and show your dialog.
You can also see your extension loaded in the extension manager.
Conclusion
This guide shows the absolute minimum code required to create a Pinta extension. Obviously, it doesn't do anything useful yet, but it provides a base to build on.
Now you can move on to implementing your actual extension: