# Writing plugins

Before writing any Anjuta plugin, please read anjuta-architecture to get a picture of how plugins interact with Anjuta shell and other plugins. Only a general overview is necessary for now. Eventually, as we proceed through this article, you can visit respective sections to read more. This is a tutorial style article and is never meant to be a cover-all document. You should read other relevent documents linked at respective places throughout this document to know further.

We are going to write the legacy Hello World plugin. It really doesn't do anything other than displaying hello world. We will then continue with an advanced version of this plugin. Unlike the basic Hello world plugin, this advanced version will have much more. In addition to having a widget where Hello World is displayed, it will also have a menu enty (UI) to display a dialog, implement a `IAnjutaFile` interface and access other plugins using their interfaces.

## Hello world plugin description, icon and UI files

We first begin by creating three helper files for our plugin. The first file is called plugin-description-filePlugin description file. This file describes our plugin to Anjuta plugin loader. Various plugin meta information are store in this file, including its name and description. Before a plugin is loaded into memory, Anjuta will examine this file and accordingly decide to load it when required.

    [Anjuta Plugin]
    _Name=Hellow
    _Description=An example hello world plugin.
    Location=anjuta-hello-world:HelloWorldPlugin
    Icon=anjuta-hello-world-plugin.png

The first two fields are name and description field. They start with '_', because the fields are translatable. Location field tells where the plugin class is located. It is of the form library:class, where library is the shared library name without the 'lib' prefix and '.so' suffix. class is the plugin class we define. Our plugin library is libanjuta-hello-world.so, so the plugin location would be anjuta-hello-world:HelloWorldPlugin. More details in plugin-description-file. Next field 'Icon', gives the name of icon file for our hello world plugin.

Next file is the XML UI definition file. This file describes the UI structure of our plugin and how it should be connected to our action functions. More details in `AnjutaUI`. The first hello world plugin doesn't use this file, but the second advanced one uses it.

    <!--*- xml -*-->
    <ui>
      <menubar name="MenuMain">
        <menu name="MenuFile" action="ActionMenuFile">
          <placeholder name="PlaceholderFileMenus">
            <menuitem name="HelloWorldAction" action="ActionFileHelloWorld" />
          </placeholder>
        </menu>
      </menubar>
    </ui>

The last file is the icon file in PNG format. All these three files are installed in different places. The prefix of their installation should match with that of Anjuta, otherwise Anjuta will not be able to find our plugin. See writing-plugins-build-setupBuild setup for installation of these files.

## Hello world plugin

This plugin does nothing other then displaying "Hello World Plugin!!" widget. The widget is added to Shell and appear as separate window. You can drag the widget and dock it various ways. This section is meant to give a quick look at how plugins are derived from `AnjutaPlugin` base class. Most of the things will be explained in writing-plugins-sourcesHello World Advanced plugin . First the plugin class is derived from the abstract class and two virtual methods activate() and deactivate() are implemented. In activate() method, we are create a label and add it to shell. Consequently, we also remove this widget in deactivate() call.

    #include <libanjuta/anjuta-plugin.h>

    typedef struct {
    	AnjutaPlugin parent;

    	/* Hello world widget */
    	GtkWidget *widget;

    } HelloWorldPlugin;

    typedef struct {
    	AnjutaPluginClass parent_class;
    } HelloWorldPluginClass;

    static gboolean
    activate_plugin (AnjutaPlugin *plugin)
    {
    	HelloWorldPlugin *hello_plugin = (HelloWorldPlugin*) plugin;

    	/* Create hello plugin widget */
    	hello_plugin->widget = gtk_label_new ("Hello World Plugin!!");

    	/* Add widget in Shell. Any number of widgets can be added */
    	anjuta_shell_add_widget (plugin->shell, hello_plugin->widget,
    	                         "AnjutaHelloWorldPlugin",
    	                         _("Hello world plugin"),
    	                         GTK_STOCK_ABOUT,
    	                         ANJUTA_SHELL_PLACEMENT_CENTER,
    	                         NULL);

    	return TRUE; /* FALSE if activation failed */
    }

    static gboolean
    deactivate_plugin (AnjutaPlugin *plugin)
    {
    	HelloWorldPlugin *hello_plugin = (HelloWorldPlugin*) plugin;

    	/* Remove widgets from Shell */
    	anjuta_shell_remove_widget (plugin->shell, hello_plugin->widget, NULL);

    	return TRUE; /* FALSE if plugin doesn't want to deactivate */
    }

    static void
    hello_world_plugin_instance_init (GObject *obj)
    {
    }

    static void
    hello_world_plugin_class_init (GObjectClass *klass)
    {
    	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
    	plugin_class->activate = activate_plugin;
    	plugin_class->deactivate = deactivate_plugin;
    }

    ANJUTA_PLUGIN_BOILERPLATE (HelloWorldPlugin, hello_world_plugin);
    ANJUTA_SIMPLE_PLUGIN (HelloWorldPlugin, hello_world_plugin);

## Hello world advanced plugin

We begin by writing the header file hello-world.h. It is a standard `GObject` class definition, minus the standard macro definitions. You can define the macros if you want, but for our hello-world plugin, we don't need it and have been removed for simplicity. Notice that our HelloWorldPlugin class is derived from abstract `AnjutaPlugin` class. All Anjuta plugins derive from this base class.

    #ifndef _HELLO_WORLD_PLUGIN_
    #define _HELLO_WORLD_PLUGIN_

    #include <libanjuta/anjuta-plugin.h>

    typedef struct {
    	AnjutaPlugin parent;

    	/* Hello world widget */
    	GtkWidget *widget;

    	/* Action group */
    	GObject* action_group;

    	/* UI merge ID. Required to unmerge it later */
    	gint uiid;

    } HelloWorldPlugin;

    typedef struct {
    	AnjutaPluginClass parent_class;
    } HelloWorldPluginClass;

    #endif

Next implement our plugin in hello-world.c file. We will be accessing a Document Manager plugin using `IAnjutaDocumentManager` interface, because all document manager plugins implement and expose this interface. If you use other interfaces, you can include their respective plugin-interfaces. For our hello-world plugin we begin by including following header files.

    /* Project configuration file */
    #include <config.h>

    /* Document manager interface */
    #include <libanjuta/interfaces/ianjuta-document-manager.h>

    /* plugin header file */
    #include "hello-world.h"

    /* Parent class. Part of standard class definition */
    static gpointer parent_class;

We have one action in our plugin and here is the callback for that. In this function, we are querying `AnjutaShell` for a plugin implementing `IAnjutaDocumentManager` interface and getting the current Editor. Editor is then checked to see if it implements `IAnjutaFile` interface, using which we determine filename of currently active editor. If the editor doesn't support `IAnjutaFile` interface, we show an error dialog.

    static void
    on_hello_action_activate (GtkAction *action, HelloWorldPlugin *plugin)
    {
    	IAnjutaDocument *doc;
    	IAnjutaDocumentManager *docman;
    	GtkWindow *parent_win;
    	gchar *filename;

    	/* We are using Anjuta widow as parent for displaying the dialog */
    	parent_win = GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell);

    	/* Query for object implementing IAnjutaDocumentManager interface */
    	docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
    	                                     IAnjutaDocumentManager, NULL);

    	/* Get current document */
    	doc = ianjuta_document_manager_get_current_document (docman, NULL);
    	filename = ianjuta_document_get_filename (doc, NULL);

    	/* Display the filename */
    	anjuta_util_dialog_info (parent_win,
    	                         "Current filename is: %s", filename);
    	g_free (filename);
    }

We then define our action entry. This is required for registering actions and UI merging. If your plugin doesn't have UI, they are not required. We have only one action, so there is only one entry defined. Read `AnjutaUI` and `GtkUIManager` for more details.

    static GtkActionEntry actions[] = {
    	{
    		"ActionFileHelloWorld",                   /* Action name */
    		GTK_STOCK_NEW,                            /* Stock icon, if any */
    		N_("_Hello world action"),                /* Display label */
    		NULL,                                     /* short-cut */
    		N_("This is hello world action"),         /* Tooltip */
    		G_CALLBACK (on_hello_action_activate)    /* action callback */
    	}
    };

We then implement activate() and deactivate() virtual methods of `AnjutaPlugin` class. They are called when plugin is activated and deactivated respectively. We put our UI merging, action registration and widgets additions in activate() method and undo them in deactivate() method.

    #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-hello-world.ui"

    static void
    activate_plugin (AnjutaPlugin *plugin)
    {
    	GtkWidget *wid;
    	AnjutaUI *ui;
    	HelloWorldPlugin *hello_plugin;
    	GtkActionGroup* action_group;

    	hello_plugin = (HelloWorldPlugin*) plugin;
    	ui = anjuta_shell_get_ui (plugin->shell, NULL);

    	/* Create hello plugin widget */
    	wid = gtk_label_new ("Hello World Plugin!!");
    	hello_plugin->widget = wid;

    	/* Add our actions */
    	action_group =
    	    anjuta_ui_add_action_group_entries (ui, "ActionGroupHello",
    	                                        _("Hello world"),
    	                                        actions,
    	                                        G_N_ELEMENTS (actions),
    	                                        plugin);
    	hello_plugin->action_group = action_group;

    	/* Merge UI */
    	hello_plugin->uiid = anjuta_ui_merge (ui, UI_FILE);

    	/* Add widget in Shell. Any number of widgets can be added */
    	anjuta_shell_add_widget (plugin->shell, wid,
    	                         "AnjutaHelloWorldPlugin",
    	                         _("HelloWorldPlugin"),
    	                         GTK_STOCK_ABOUT,
    	                         ANJUTA_SHELL_PLACEMENT_CENTER,
    	                         NULL);

    	return TRUE; /* FALSE if activation failed */
    }

    static gboolean
    deactivate_plugin (AnjutaPlugin *plugin)
    {
    	AnjutaUI *ui;
    	HelloWorldPlugin *hello_plugin;

    	hello_plugin = (HelloWorldPlugin*) plugin;
    	ui = anjuta_shell_get_ui (plugin->shell, NULL);

    	/* Remove widgets from Shell */
    	anjuta_shell_remove_widget (plugin->shell,
    	                            hello_plugin->widget,
    	                            NULL);
    	/* Unmerge UI */
    	anjuta_ui_unmerge (ui, hello_plugin->uiid);

    	/* Remove Action groups */
    	anjuta_ui_remove_action_group (ui, hello_plugin->action_group);

    	/* FALSE if plugin doesn't want to deactivate */
    	return TRUE;
    }

Followed by standard class definition. Notice that activate() and deactivate() methods are overridden in class_init() function.

    static void
    hello_world_plugin_instance_init (GObject *obj)
    {
    	HelloWorldPlugin *plugin = (HelloWorldPlugin*) obj;
    	plugin->uiid = 0;
    	plugin->widget = NULL;
    	plugin->action_group = NULL;
    }

    static void
    hello_world_plugin_class_init (GObjectClass *klass)
    {
    	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);

    	parent_class = g_type_class_peek_parent (klass);

    	plugin_class->activate = activate_plugin;
    	plugin_class->deactivate = deactivate_plugin;
    }

    /* This line will change when we implement interfaces */
    ANJUTA_PLUGIN_BOILERPLATE (HelloWorldPlugin, hello_world_plugin);

    /* This sets up codes to register our plugin */
    ANJUTA_SIMPLE_PLUGIN (HelloWorldPlugin, hello_world_plugin);

That's it. We can now create the build structure to build it.

## Build setup

To check for libanjuta library and setup compiler flags, add the following lines in your projects's configure.in file:

    PKG_CONFIG_PACKAGE(LIBANJUTA, libanjuta >= 2.0)
    AC_SUBST(LIBANJUTA_CFLAGS)
    AC_SUBST(LIBANJUTA_LIBS)

Configure variables LIBANJUTA_CFLAGS and LIBANJUTA_LIBS will contain the necessary compiler flags and libraries to include and are available to be used in your Makefile.am file. In your Makefile.am (of the directory where your plugin sources reside), use above configure variables.

Add the following lines in Makefile.am to install the UI file correctly. If you plugin doesn't have a UI, this could be skipped.

    # Plugin UI file
    anjuta_uidir = $(datadir)/anjuta/ui
    anjuta_ui_DATA =  anjuta-hello.ui

Following lines to install the icon file.

    # Plugin Icon file
    plugin_icondir = $(datadir)/pixmaps/anjuta
    plugin_icon_DATA = anjuta-hello-plugin.png

Following lines to install the plugin description file. This make rule will automatically merge translations and create .plugin file from .plugin.in file.

    # Plugin description file
    plugin_in_files = anjuta-hello.plugin.in
    %.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; \
    	$(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u \
    		-c $(top_builddir)/po/.intltool-merge-cache
    anjuta_plugindir = $(libdir)/anjuta
    anjuta_plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)

Add following lines to build and install our plugin shared library. Notice that we are using libanjuta configure variables now.

    INCLUDES = $(LIBANJUTA_CFLAGS)
    plugin_LTLIBRARIES = libanjuta-hello.la
    libanjuta_hello_SOURCES = \
    	hello-world.c \
    	hello-world.h
    libanjuta_hello_LIADD = $(LIBANJUTA_LIBS)