- API changes:
Replace p_ui->get_toolbar_insert_position() with p_plugin->add_toolbar_item(), which also adds a separator when the first item is added. Add 'GeanyPlugin *geany_plugin' plugin symbol, partly to replace plugin_info (now deprecated), mainly to identify a plugin and hold private implementation fields for plugin utility functions. (plugin_info will be removed after the 0.15 release.) - Code changes: Add ui_auto_separator_add_ref() to hide separator-like widgets when their visible group elements are hidden or destroyed. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3074 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
parent
be3849e33a
commit
d8d727752e
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
2008-10-13 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
||||
|
||||
* src/ui_utils.h, src/plugindata.h, src/plugins.c, src/ui_utils.c,
|
||||
doc/Doxyfile.in, doc/pluginsymbols.c, plugins/demoplugin.c,
|
||||
plugins/pluginmacros.h:
|
||||
- API changes:
|
||||
Replace p_ui->get_toolbar_insert_position() with
|
||||
p_plugin->add_toolbar_item(), which also adds a separator when the
|
||||
first item is added.
|
||||
Add 'GeanyPlugin *geany_plugin' plugin symbol, partly to replace
|
||||
plugin_info (now deprecated), mainly to identify a plugin and hold
|
||||
private implementation fields for plugin utility functions.
|
||||
(plugin_info will be removed after the 0.15 release.)
|
||||
- Code changes:
|
||||
Add ui_auto_separator_add_ref() to hide separator-like widgets when
|
||||
their visible group elements are hidden or destroyed.
|
||||
|
||||
|
||||
2008-10-12 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
* src/highlighting.c:
|
||||
|
@ -226,7 +226,7 @@ SEARCH_INCLUDES = NO
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
# make G_GNUC_PRINTF a no-op unless doxygen would ignore functions with varargs
|
||||
PREDEFINED = "G_GNUC_PRINTF(x,y)=" GEANY_DISABLE_DEPRECATED
|
||||
PREDEFINED = "G_GNUC_PRINTF(x,y)=" GEANY_DISABLE_DEPRECATED HAVE_PLUGINS
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -43,22 +43,26 @@ gint plugin_version_check(gint);
|
||||
* @param info The data struct which should be initialized by this function. */
|
||||
void plugin_set_info(PluginInfo *info);
|
||||
|
||||
/** Basic information about a plugin, which is set in plugin_set_info(). */
|
||||
const PluginInfo* plugin_info;
|
||||
/** @deprecated Use geany_plugin->info instead.
|
||||
* Basic information about a plugin, which is set in plugin_set_info(). */
|
||||
const PluginInfo *plugin_info;
|
||||
|
||||
/** Basic information for the plugin and identification. */
|
||||
const GeanyPlugin *geany_plugin;
|
||||
|
||||
/** Geany owned data pointers.
|
||||
* Example: @c assert(geany_data->app->configdir != NULL); */
|
||||
const GeanyData* geany_data;
|
||||
const GeanyData *geany_data;
|
||||
|
||||
/** Geany owned function pointers, split into groups.
|
||||
* Example: @c geany_functions->p_document->new_file(NULL, NULL, NULL);
|
||||
*
|
||||
* Note: Usually plugins would use the pluginmacros.h file and just call:
|
||||
* @c p_document->new_file(NULL, NULL, NULL); */
|
||||
const GeanyFunctions* geany_functions;
|
||||
const GeanyFunctions *geany_functions;
|
||||
|
||||
/** Plugin owned fields, including flags. */
|
||||
PluginFields* plugin_fields;
|
||||
PluginFields *plugin_fields;
|
||||
|
||||
/** An array for connecting GeanyObject events, which should be terminated with
|
||||
* @c {NULL, NULL, FALSE, NULL}. See @link signals Signal documentation @endlink. */
|
||||
|
@ -44,15 +44,15 @@
|
||||
|
||||
|
||||
/* These items are set by Geany before plugin_init() is called. */
|
||||
PluginInfo *plugin_info;
|
||||
GeanyPlugin *geany_plugin;
|
||||
PluginFields *plugin_fields;
|
||||
GeanyData *geany_data;
|
||||
GeanyFunctions *geany_functions;
|
||||
|
||||
|
||||
/* Check that Geany supports plugin API version 7 or later, and check
|
||||
/* Check that the running Geany supports the plugin API used below, and check
|
||||
* for binary compatibility. */
|
||||
PLUGIN_VERSION_CHECK(64)
|
||||
PLUGIN_VERSION_CHECK(99)
|
||||
|
||||
/* All plugins must set name, description, version and author. */
|
||||
PLUGIN_SET_INFO(_("Demo"), _("Example plugin."), VERSION, _("The Geany developer team"))
|
||||
@ -75,7 +75,7 @@ item_activate(GtkMenuItem *menuitem, gpointer gdata)
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", welcome_text);
|
||||
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
|
||||
_("(From the %s plugin)"), plugin_info->name);
|
||||
_("(From the %s plugin)"), geany_plugin->info->name);
|
||||
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
|
@ -52,6 +52,7 @@
|
||||
#define p_main geany_functions->p_main /**< See main.h */
|
||||
#define p_msgwindow geany_functions->p_msgwindow /**< See msgwindow.h */
|
||||
#define p_navqueue geany_functions->p_navqueue /**< See navqueue.h */
|
||||
#define p_plugin geany_functions->p_plugin /**< See plugins.c */
|
||||
#define p_sci geany_functions->p_sci /**< See sciwrappers.h */
|
||||
#define p_search geany_functions->p_search /**< See search.h */
|
||||
#define p_support geany_functions->p_support /**< See support.h */
|
||||
|
@ -41,13 +41,13 @@
|
||||
enum {
|
||||
/** The Application Programming Interface (API) version, incremented
|
||||
* whenever any plugin data types are modified or appended to. */
|
||||
GEANY_API_VERSION = 98,
|
||||
GEANY_API_VERSION = 99,
|
||||
|
||||
/** The Application Binary Interface (ABI) version, incremented whenever
|
||||
* existing fields in the plugin data types have to be changed or reordered. */
|
||||
/* This should usually stay the same if fields are only appended, assuming only pointers to
|
||||
* structs and not structs themselves are declared by plugins. */
|
||||
GEANY_ABI_VERSION = 46
|
||||
GEANY_ABI_VERSION = 47
|
||||
};
|
||||
|
||||
/** Check the plugin can be loaded by Geany.
|
||||
@ -65,8 +65,8 @@ enum {
|
||||
}
|
||||
|
||||
|
||||
/** Plugin info structure to hold basic information about a plugin.
|
||||
* Should usually be set with PLUGIN_SET_INFO(). */
|
||||
/** Basic information about a plugin available to Geany without loading the plugin.
|
||||
* The fields are set in plugin_set_info(), usually with the PLUGIN_SET_INFO() macro. */
|
||||
typedef struct PluginInfo
|
||||
{
|
||||
/** The name of the plugin. */
|
||||
@ -80,6 +80,17 @@ typedef struct PluginInfo
|
||||
}
|
||||
PluginInfo;
|
||||
|
||||
|
||||
/** Basic information for the plugin and identification. */
|
||||
typedef struct GeanyPlugin
|
||||
{
|
||||
PluginInfo *info; /**< Fields set in plugin_set_info(). */
|
||||
|
||||
struct GeanyPluginPrivate *priv; /* private */
|
||||
}
|
||||
GeanyPlugin;
|
||||
|
||||
|
||||
/** Set the plugin name and some other basic information about a plugin.
|
||||
* This declares a function, so you can use the _() translation macro for arguments.
|
||||
*
|
||||
@ -198,6 +209,7 @@ typedef struct GeanyFunctions
|
||||
struct NavQueueFuncs *p_navqueue; /**< See navqueue.h */
|
||||
struct EditorFuncs *p_editor; /**< See editor.h */
|
||||
struct MainFuncs *p_main; /**< See main.h */
|
||||
struct PluginFuncs *p_plugin; /**< See plugins.c */
|
||||
}
|
||||
GeanyFunctions;
|
||||
|
||||
@ -336,7 +348,6 @@ typedef struct UIUtilsFuncs
|
||||
void (*table_add_row) (GtkTable *table, gint row, ...) G_GNUC_NULL_TERMINATED;
|
||||
GtkWidget* (*path_box_new) (const gchar *title, GtkFileChooserAction action, GtkEntry *entry);
|
||||
GtkWidget* (*button_new_with_image) (const gchar *stock_id, const gchar *text);
|
||||
gint (*get_toolbar_insert_position) (void);
|
||||
}
|
||||
UIUtilsFuncs;
|
||||
|
||||
@ -466,6 +477,14 @@ typedef struct EditorFuncs
|
||||
EditorFuncs;
|
||||
|
||||
|
||||
/* See plugins.c */
|
||||
typedef struct PluginFuncs
|
||||
{
|
||||
void (*add_toolbar_item)(GeanyPlugin *plugin, GtkToolItem *item);
|
||||
}
|
||||
PluginFuncs;
|
||||
|
||||
|
||||
/* Deprecated aliases */
|
||||
#ifndef GEANY_DISABLE_DEPRECATED
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
|
||||
/* Code to manage, load and unload plugins. */
|
||||
/** @file plugins.c
|
||||
* Plugin utility functions. */
|
||||
|
||||
#include "geany.h"
|
||||
|
||||
@ -65,12 +67,22 @@
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct GeanyPluginPrivate
|
||||
{
|
||||
GeanyAutoSeparator toolbar_separator;
|
||||
}
|
||||
GeanyPluginPrivate;
|
||||
|
||||
|
||||
typedef struct Plugin
|
||||
{
|
||||
GModule *module;
|
||||
gchar *filename; /* plugin filename (/path/libname.so) */
|
||||
PluginInfo info; /* plugin name, description, etc */
|
||||
PluginFields fields;
|
||||
GeanyPlugin public; /* fields the plugin can read */
|
||||
GeanyPluginPrivate priv; /* GeanyPlugin type private data */
|
||||
|
||||
gulong *signal_ids; /* signal IDs to disconnect when unloading */
|
||||
gsize signal_ids_len;
|
||||
GeanyKeyGroup *key_group;
|
||||
@ -93,6 +105,12 @@ static GtkWidget *menu_separator = NULL;
|
||||
|
||||
static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data);
|
||||
|
||||
void plugin_add_toolbar_item(GeanyPlugin *plugin, GtkToolItem *item);
|
||||
|
||||
|
||||
static PluginFuncs plugin_funcs = {
|
||||
&plugin_add_toolbar_item
|
||||
};
|
||||
|
||||
static DocumentFuncs doc_funcs = {
|
||||
&document_new_file,
|
||||
@ -185,7 +203,6 @@ static UIUtilsFuncs uiutils_funcs = {
|
||||
&ui_table_add_row,
|
||||
&ui_path_box_new,
|
||||
&ui_button_new_with_image,
|
||||
&ui_get_toolbar_insert_position
|
||||
};
|
||||
|
||||
static DialogFuncs dialog_funcs = {
|
||||
@ -265,7 +282,8 @@ static GeanyFunctions geany_functions = {
|
||||
&filetype_funcs,
|
||||
&navqueue_funcs,
|
||||
&editor_funcs,
|
||||
&main_funcs
|
||||
&main_funcs,
|
||||
&plugin_funcs
|
||||
};
|
||||
|
||||
static GeanyData geany_data;
|
||||
@ -454,6 +472,7 @@ add_kb_group(Plugin *plugin)
|
||||
static void
|
||||
plugin_init(Plugin *plugin)
|
||||
{
|
||||
GeanyPlugin **p_geany_plugin;
|
||||
PluginCallback *callbacks;
|
||||
PluginInfo **p_info;
|
||||
PluginFields **plugin_fields;
|
||||
@ -461,6 +480,9 @@ plugin_init(Plugin *plugin)
|
||||
GeanyFunctions **p_geany_functions;
|
||||
|
||||
/* set these symbols before plugin_init() is called */
|
||||
g_module_symbol(plugin->module, "geany_plugin", (void *) &p_geany_plugin);
|
||||
if (p_geany_plugin)
|
||||
*p_geany_plugin = &plugin->public;
|
||||
g_module_symbol(plugin->module, "plugin_info", (void *) &p_info);
|
||||
if (p_info)
|
||||
*p_info = &plugin->info;
|
||||
@ -608,6 +630,8 @@ plugin_new(const gchar *fname, gboolean init_plugin, gboolean add_to_list)
|
||||
|
||||
plugin->filename = g_strdup(fname);
|
||||
plugin->module = module;
|
||||
plugin->public.info = &plugin->info;
|
||||
plugin->public.priv = &plugin->priv;
|
||||
|
||||
if (init_plugin)
|
||||
plugin_init(plugin);
|
||||
@ -641,6 +665,7 @@ static gboolean is_active_plugin(Plugin *plugin)
|
||||
static void
|
||||
plugin_unload(Plugin *plugin)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
if (is_active_plugin(plugin) && plugin->cleanup)
|
||||
plugin->cleanup();
|
||||
@ -650,6 +675,10 @@ plugin_unload(Plugin *plugin)
|
||||
if (plugin->key_group)
|
||||
g_ptr_array_remove_fast(keybinding_groups, plugin->key_group);
|
||||
|
||||
widget = plugin->priv.toolbar_separator.widget;
|
||||
if (widget)
|
||||
gtk_widget_destroy(widget);
|
||||
|
||||
active_plugin_list = g_list_remove(active_plugin_list, plugin);
|
||||
geany_debug("Unloaded: %s", plugin->filename);
|
||||
}
|
||||
@ -1194,4 +1223,44 @@ static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data)
|
||||
gtk_widget_show_all(pm_widgets.dialog);
|
||||
}
|
||||
|
||||
|
||||
/** Insert a toolbar item before the Quit button, or after the previous plugin toolbar item.
|
||||
* A separator is added on the first call to this function, and will be shown when @a item is
|
||||
* shown; hidden when @a item is hidden.
|
||||
* @note You should still destroy @a item yourself, usually in @ref plugin_cleanup().
|
||||
* @param plugin Must be @ref geany_plugin.
|
||||
* @param item The item to add. */
|
||||
void plugin_add_toolbar_item(GeanyPlugin *plugin, GtkToolItem *item)
|
||||
{
|
||||
GtkToolbar *toolbar = GTK_TOOLBAR(main_widgets.toolbar);
|
||||
gint pos;
|
||||
GeanyAutoSeparator *autosep;
|
||||
|
||||
g_return_if_fail(plugin);
|
||||
autosep = &plugin->priv->toolbar_separator;
|
||||
|
||||
if (!autosep->widget)
|
||||
{
|
||||
GtkToolItem *sep;
|
||||
|
||||
pos = ui_get_toolbar_insert_position();
|
||||
/* pos should be valid even if the quit btn is hidden */
|
||||
g_return_if_fail(pos >= 0);
|
||||
gtk_toolbar_insert(toolbar, item, pos);
|
||||
|
||||
sep = gtk_separator_tool_item_new();
|
||||
gtk_toolbar_insert(toolbar, sep, pos + 1);
|
||||
autosep->widget = GTK_WIDGET(sep);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = gtk_toolbar_get_item_index(toolbar, GTK_TOOL_ITEM(autosep->widget));
|
||||
g_return_if_fail(pos >= 0);
|
||||
gtk_toolbar_insert(toolbar, item, pos);
|
||||
}
|
||||
/* hide the separator widget if there are no toolbar items showing for the plugin */
|
||||
ui_auto_separator_add_ref(autosep, GTK_WIDGET(item));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1531,7 +1531,7 @@ void ui_init(void)
|
||||
}
|
||||
|
||||
|
||||
/** Returns the position for adding new toolbar items. The returned position can be used
|
||||
/* Returns the position for adding new toolbar items. The returned position can be used
|
||||
* to add new toolbar items with @c gtk_toolbar_insert(). The toolbar object can be accessed
|
||||
* with @a geany->main_widgets->toolbar.
|
||||
* The position is always the last one before the Quit button (if it is shown).
|
||||
@ -1550,3 +1550,59 @@ gint ui_get_toolbar_insert_position(void)
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static void auto_separator_update(GeanyAutoSeparator *autosep)
|
||||
{
|
||||
g_return_if_fail(autosep->ref_count >= 0);
|
||||
|
||||
if (autosep->widget)
|
||||
ui_widget_show_hide(autosep->widget, autosep->ref_count > 0);
|
||||
}
|
||||
|
||||
|
||||
static void on_auto_separator_item_show_hide(GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GeanyAutoSeparator *autosep = user_data;
|
||||
|
||||
if (GTK_WIDGET_VISIBLE(widget))
|
||||
autosep->ref_count++;
|
||||
else
|
||||
autosep->ref_count--;
|
||||
|
||||
auto_separator_update(autosep);
|
||||
}
|
||||
|
||||
|
||||
static void on_auto_separator_item_destroy(GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GeanyAutoSeparator *autosep = user_data;
|
||||
|
||||
/* GTK_WIDGET_VISIBLE won't work now the widget is being destroyed,
|
||||
* so assume widget was visible */
|
||||
autosep->ref_count--;
|
||||
autosep->ref_count = MAX(autosep->ref_count, 0);
|
||||
auto_separator_update(autosep);
|
||||
}
|
||||
|
||||
|
||||
/* Show the separator widget if @a item or another is visible. */
|
||||
/* Note: This would be neater taking a widget argument, setting a "visible-count"
|
||||
* property, and using reference counting to keep the widget alive whilst its visible group
|
||||
* is alive. */
|
||||
void ui_auto_separator_add_ref(GeanyAutoSeparator *autosep, GtkWidget *item)
|
||||
{
|
||||
/* set widget ptr NULL when widget destroyed */
|
||||
if (autosep->ref_count == 0)
|
||||
g_signal_connect(autosep->widget, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &autosep->widget);
|
||||
|
||||
if (GTK_WIDGET_VISIBLE(item))
|
||||
{
|
||||
autosep->ref_count++;
|
||||
auto_separator_update(autosep);
|
||||
}
|
||||
g_signal_connect(item, "show", G_CALLBACK(on_auto_separator_item_show_hide), autosep);
|
||||
g_signal_connect(item, "hide", G_CALLBACK(on_auto_separator_item_show_hide), autosep);
|
||||
g_signal_connect(item, "destroy", G_CALLBACK(on_auto_separator_item_destroy), autosep);
|
||||
}
|
||||
|
||||
|
@ -125,9 +125,17 @@ UIWidgets;
|
||||
extern UIWidgets ui_widgets;
|
||||
|
||||
|
||||
/* The following block of functions are more generic functions and closely related to
|
||||
/* The following block of types & functions are more generic and closely related to
|
||||
* certain GTK+ widgets. */
|
||||
|
||||
typedef struct GeanyAutoSeparator
|
||||
{
|
||||
GtkWidget *widget; /* e.g. GtkSeparatorToolItem, GtkSeparatorMenuItem */
|
||||
gint ref_count; /* set to zero initially */
|
||||
}
|
||||
GeanyAutoSeparator;
|
||||
|
||||
|
||||
void ui_widget_show_hide(GtkWidget *widget, gboolean show);
|
||||
|
||||
void ui_widget_modify_font_from_string(GtkWidget *wid, const gchar *str);
|
||||
@ -151,6 +159,8 @@ void ui_setup_open_button_callback(GtkWidget *open_btn, const gchar *title,
|
||||
|
||||
void ui_table_add_row(GtkTable *table, gint row, ...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
void ui_auto_separator_add_ref(GeanyAutoSeparator *autosep, GtkWidget *item);
|
||||
|
||||
/* End of 'generic' functions */
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user