AnjutaPlugin

AnjutaPlugin — Anjuta plugin base class from which all plugins are derived.

Synopsis




            AnjutaPlugin;
void        (*AnjutaPluginValueAdded)       (AnjutaPlugin *plugin,
                                             const char *name,
                                             const GValue *value,
                                             gpointer user_data);
void        (*AnjutaPluginValueRemoved)     (AnjutaPlugin *plugin,
                                             const char *name,
                                             gpointer user_data);
gboolean    anjuta_plugin_is_active         (AnjutaPlugin *plugin);
gboolean    anjuta_plugin_activate          (AnjutaPlugin *plugin);
gboolean    anjuta_plugin_deactivate        (AnjutaPlugin *plugin);
guint       anjuta_plugin_add_watch         (AnjutaPlugin *plugin,
                                             const gchar *name,
                                             AnjutaPluginValueAdded added,
                                             AnjutaPluginValueRemoved removed,
                                             gpointer user_data);
void        anjuta_plugin_remove_watch      (AnjutaPlugin *plugin,
                                             guint id,
                                             gboolean send_remove);
#define     ANJUTA_PLUGIN_BEGIN             (class_name, prefix)
#define     ANJUTA_PLUGIN_END
#define     ANJUTA_PLUGIN_ADD_INTERFACE     (prefix,interface_type)
#define     ANJUTA_PLUGIN_BOILERPLATE       (class_name, prefix)
#define     ANJUTA_SIMPLE_PLUGIN            (class_name, prefix)


Object Hierarchy


  GObject
   +----AnjutaPlugin

Properties


  "shell"                AnjutaShell           : Read / Write / Construct Only

Signal Prototypes


"activated" void        user_function      (AnjutaPlugin *anjutaplugin,
                                            gpointer user_data);
"deactivated"
            void        user_function      (AnjutaPlugin *anjutaplugin,
                                            gpointer user_data);

Description

Anjuta plugins are components which are loaded in Anjuta IDE shell either on startup or on demand to perform various subtasks. Plugins are specialized in doing only a very specific task and can let other plugins interract with it using interfaces.

A plugin class is derived from AnjutaPlugin class and will be used by shell to instanciate any number of plugin objects. Three member data in AnjutaPlugin are directly accessible from outside (usually accessed by the plugin and its associated interface implementations only ). They are:

shell

It is the shell in which the plugin is loaded. See AnjutaShell for more details.

ui

It is the UI manager where the plugin will merge or unmerge its UI elements (menus, toolbars and popup menus). See AnjutaUI for more details.

prefs

A AnjutaPreferences object, where the plugin can register its prefereces.

When a plugin class is derived from AnjutaPlugin, the virtual mehtods activate and deactivate must be implemented. The activate method is used to activate the plugin. Note that plugin activation is different from plugin instance initialization. Instance initialization is use to do internal initialization, while activate method is used to setup the plugin in shell, UI and preferences. Other plugins can also be queried in activate method.

Following things should be done in activate method.

  1. Register UI Actions: Use anjuta_ui_add_action_group_entries() or anjuta_ui_add_toggle_action_group_entries() to add your action groups.

  2. Merge UI definition file: Use anjuta_ui_merge() to merge a UI file. See AnjutaUI for more detail.

  3. Add widgets to Anjuta Shell: If the plugin has one or more widgets as its User Interface, they can be added with anjuta_shell_add_widget().

  4. Setup value watches with anjuta_plugin_add_watch().

static void
on_action_activate (GtkAction *action, SamplePlugin *plugin)
{
	/* Do some action */
}

static GtkActionEntry actions_file[] = {
	{
		"ActionFileSample",                       /* Action name */
		GTK_STOCK_NEW,                            /* Stock icon, if any */
		N_("_Sample action"),                     /* Display label */
		NULL,                                     /* short-cut */
		N_("Sample action"),                      /* Tooltip */
		G_CALLBACK (on_sample_action_activate)    /* action callback */
	}
};

static void
activate_plugin (AnjutaPlugin *plugin)
{
	...
	/* Add action groups */
	anjuta_ui_add_action_group_entries (ui, "ActionGroupSampleFile",
	                                    _("Sample file operations"),
	                                    actions_file,
	                                    G_N_ELEMENTS (actions_file),
	                                    plugin);
	/* Merge UI */
	sample_plugin->uiid = anjuta_ui_merge (plugin->ui, "/path/to/sample.ui");
	
	/* Add widgets */
	anjuta_shell_add_widget (plugin->shell, widget, "AnjutaSamplePlugin",
	                         _("SamplePlugin"), NULL);
	...
}

deactivate method undos all the above. That is, it removes widgets from the shell, unmerges UI and removes the action groups.

Plugins interact with each other using interfaces. A plugin can expose an interface which will let other plugins find it. Any number of interfaces can be exposed by a plugin. These exposed interfaces are called Primary interfaces of the plugin. The condition for the interfaces to be primary is that they should be independent (i.e. an external entity requesting to use a primary interface should not require other primary interfaces). For example, an editor plugin can implement IAnjutaEditor, IAnjutaStream and IAnjutaFile interfaces and expose them as primary interfaces, because they are independent. Primary interfaces exposed by a plugin are exported in its plugin meta-data file, so that plugin manager could register them.

Any other interfaces implemented by the plugin are called Secondary interfaces and they generally depend on one or more primary interfaces. For example, IAnjutaEditor is the primary interface of anjuta-editor plugin, but it also implements secondary interfaces IAnjutaEditorGutter and IAnjutaEditorBuffer. Notice that secondary interfaces IAnjutaEditorGutter and IAnjutaEditorBuffer depend on IAnjutaEditor interface.

The purpose of distinguishing between primary and secondary interfaces is only at plugin level. At code level, they behave just the same and there is no difference. So, a natural sequence for a plugin to communicate with another plugin is:

  1. Query the shell for a plugin implemeting the primary interface using anjuta_shell_get_interface(). It will return an implemetation of the interface (or NULL if not found). Do not save this object for longer use, because the implementor plugin can change anytime and a different plugin implementing the same primary interface may be activated.

    GError *err = NULL;
    IAnjutaDocumentManager *docman;
    IAnjutaEditor *editor;
    
    docman = anjuta_shell_get_interface (ANJUTA_PLUGIN(plugin)->shell,
                                         IAnjutaDocumentManager, &err);
    if (err)
    {
    	g_warning ("Error encountered: s", err->message);
    	g_error_free (err);
    	return;
    }
    
    editor = ianjuta_document_manager_get_current_editor (docman, &err);
    if (err)
    {
    	g_warning ("Error encountered: s", err->message);
    	g_error_free (err);
    	return;
    }
    /* Do anything with editor object */
    ianjuta_editor_goto_line (editor, 200);
    ...
    				

  2. A primary interface of a plugin can be directly used, but to use a secondary interface, make sure to check if the plugin object implements it. For example, to check if editor plugin implements IAnjutaEditorGutter interface, do something like:

    /* Check if the plugin implements IAnjutaEditorGutter interface */
    if (IANJUTA_IS_EDITOR_GUTTER(editor))
    {
    	/* plugin implements it, so use it */
    	ianjuta_editor_gutter_set_marker(IANJUTA_EDITOR_GUTTER (editor),
    	                                 ANJUTA_EDITOR_MARKER_1,
    	                                 line_number, &err);
    }
    else
    {
    	/* plugin does not implement it */
    	/* Do something else */
    }
    				

Plugins can also communicate with outside using Shell's Values System. Values are objects exported by plugins to make them available to other plugins. Read AnjutaShell documentation for more detail on Values System. A plugin can set up watches with anjuta_plugin_add_watch() to get notifications for values exported by other plugins.

Values are very unreliable way of passing objects between plugins, but are nevertheless very useful (and quicker to code). It must be used with care. As a rule of thumb, a plugin should only watch values of other trusted plugins. For example, a group of plugins forming a subsystem can comfortably use values to pass objects and notifications. Use anjuta_plugin_add_watch() and anjuta_plugin_remove_watch() to add or remove value watches.

Details

AnjutaPlugin

typedef struct _AnjutaPlugin AnjutaPlugin;


AnjutaPluginValueAdded ()

void        (*AnjutaPluginValueAdded)       (AnjutaPlugin *plugin,
                                             const char *name,
                                             const GValue *value,
                                             gpointer user_data);

The callback to pass to anjuta_plugin_add_watch(). When a name value is added to shell by another plugin, this callback will be called.

plugin : The AnjutaPlugin based plugin
name : name of value being added.
value : value of value being added.
user_data : User data set during anjuta_plugin_add_watch()

AnjutaPluginValueRemoved ()

void        (*AnjutaPluginValueRemoved)     (AnjutaPlugin *plugin,
                                             const char *name,
                                             gpointer user_data);

The callback to pass to anjuta_plugin_add_watch(). When the name value is removed from the shell (by the plugin exporting this value), this callback will be called.

plugin : The AnjutaPlugin based plugin
name : name of value being added.
user_data : User data set during anjuta_plugin_add_watch()

anjuta_plugin_is_active ()

gboolean    anjuta_plugin_is_active         (AnjutaPlugin *plugin);

Returns TRUE if the plugin has been activated.

plugin : a AnjutaPlugin derived class object.
Returns : TRUE if activated, FALSE otherwise.

anjuta_plugin_activate ()

gboolean    anjuta_plugin_activate          (AnjutaPlugin *plugin);

Activates the plugin by calling activate() virtual method. All plugins should derive their classes from this virtual class and implement this method.

plugin : a AnjutaPlugin derived class object.
Returns : TRUE if sucessfully activated, FALSE otherwise.

anjuta_plugin_deactivate ()

gboolean    anjuta_plugin_deactivate        (AnjutaPlugin *plugin);

Deactivates the plugin by calling deactivate() virtual method. All plugins should derive their classes from this virtual class and implement this method.

plugin : a AnjutaPlugin derived class object.
Returns : TRUE if sucessfully activated, FALSE otherwise.

anjuta_plugin_add_watch ()

guint       anjuta_plugin_add_watch         (AnjutaPlugin *plugin,
                                             const gchar *name,
                                             AnjutaPluginValueAdded added,
                                             AnjutaPluginValueRemoved removed,
                                             gpointer user_data);

Adds a watch for name value. When the value is added in shell, the added callback will be called and when it is removed, the removed callback will be called. The returned ID is used to remove the watch later.

plugin : a AnjutaPlugin derived class object.
name : Name of the value to watch.
added : Callback to call when the value is added.
removed : Callback to call when the value is removed.
user_data : User data to pass to callbacks.
Returns : Watch ID.

anjuta_plugin_remove_watch ()

void        anjuta_plugin_remove_watch      (AnjutaPlugin *plugin,
                                             guint id,
                                             gboolean send_remove);

Removes the watch represented by id (which was returned by anjuta_plugin_add_watch()).

plugin : a AnjutaPlugin derived class object.
id : Watch id to remove.
send_remove : If true, calls value_removed callback.

ANJUTA_PLUGIN_BEGIN()

#define     ANJUTA_PLUGIN_BEGIN(class_name, prefix)

This is a convienient macro defined to make it easy to write plugin classes . This macro begins the class type definition. member function prefix _class_init and prefix _instance_init should be statically defined before using this macro.

The class type definition is finished with ANJUTA_PLUGIN_END() macro. In between which any number of interface definitions could be added with ANJUTA_PLUGIN_ADD_INTERFACE() macro.

class_name : Name of the class. e.g. EditorPlugin
prefix : prefix of member function names. e.g. editor_plugin

ANJUTA_PLUGIN_END

#define     ANJUTA_PLUGIN_END

Ends the plugin class type definition started with ANJUTA_PLUGIN_BEGIN()


ANJUTA_PLUGIN_ADD_INTERFACE()

#define     ANJUTA_PLUGIN_ADD_INTERFACE(prefix,interface_type)

This is a convienient macro defined to make it easy to add interfaces to a plugin type. prefix _iface_init should be statically defined before using this macro. This macro should be called between ANJUTA_PLUGIN_BEGIN() and ANJUTA_PLUGIN_END() macros.

prefix : prefix of member function names.
interface_type : Interface type. e.g. IANJUTA_TYPE_EDITOR

ANJUTA_PLUGIN_BOILERPLATE()

#define     ANJUTA_PLUGIN_BOILERPLATE(class_name, prefix)

This macro is similar to using ANJUTA_PLUGIN_BEGIN() and then immediately using ANJUTA_PLUGIN_END(). It is basically a plugin type definition macro that does not have any interface implementation.

class_name : Name of the class. e.g EditorPlugin
prefix : prefix of member function names. e.g. editor_plugin

ANJUTA_SIMPLE_PLUGIN()

#define     ANJUTA_SIMPLE_PLUGIN(class_name, prefix)

Sets up necessary codes for the plugin factory to know the class type of of the plugin. This macro is generally used at the end of plugin class and member functions definitions.

class_name : Name of the class. e.g. EditorPlugin
prefix : prefix of member function names. e.g. editor_plugin

Properties

The "shell" property

  "shell"                AnjutaShell           : Read / Write / Construct Only

Anjuta shell that will contain the plugin.

Signals

The "activated" signal

void        user_function                  (AnjutaPlugin *anjutaplugin,
                                            gpointer user_data);

anjutaplugin : the object which received the signal.
user_data : user data set when the signal handler was connected.

The "deactivated" signal

void        user_function                  (AnjutaPlugin *anjutaplugin,
                                            gpointer user_data);

anjutaplugin : the object which received the signal.
user_data : user data set when the signal handler was connected.