# HG changeset patch # User Sadrul Habib Chowdhury # Date 1162073692 0 # Node ID 97977138cf29c5cda3c5451f83d03d6f8eb3f566 # Parent 852803694be31a4cf13c5f2903346e089e6c0da1 [gaim-migrate @ 17612] Add a 'MenuItemCheck' thing. Use GntMenu for the context-menu in the buddylist. This patch has 666 lines ... but I'm sure it's a good patch! committer: Tailor Script diff -r 852803694be3 -r 97977138cf29 console/gntblist.c --- a/console/gntblist.c Sat Oct 28 20:38:25 2006 +0000 +++ b/console/gntblist.c Sat Oct 28 22:14:52 2006 +0000 @@ -39,6 +39,9 @@ #include "gntentry.h" #include "gntlabel.h" #include "gntline.h" +#include "gntmenu.h" +#include "gntmenuitem.h" +#include "gntmenuitemcheck.h" #include "gnttree.h" #include "gntwindow.h" @@ -597,29 +600,39 @@ } static void -remove_context_menu(GGBlist *ggblist) +context_menu_callback(GntMenuItem *item, gpointer data) { - if (ggblist->context) - gnt_widget_destroy(ggblist->context->parent); - ggblist->context = NULL; - ggblist->cnode = NULL; + GaimMenuAction *action = data; + GaimBlistNode *node = ggblist->cnode; + if (action) { + void (*callback)(GaimBlistNode *, gpointer); + callback = (void (*)(GaimBlistNode *, gpointer))action->callback; + if (callback) + callback(action->data, node); + else + return; + } } static void -gnt_append_menu_action(GntTree *tree, GaimMenuAction *action, gpointer parent) +gnt_append_menu_action(GntMenu *menu, GaimMenuAction *action, gpointer parent) { GList *list; + GntMenuItem *item; + if (action == NULL) return; - gnt_tree_add_row_last(tree, action, - gnt_tree_create_row(tree, action->label), parent); + item = gnt_menuitem_new(action->label); + gnt_menuitem_set_callback(GNT_MENUITEM(item), context_menu_callback, action); + gnt_menu_add_item(menu, GNT_MENUITEM(item)); + for (list = action->children; list; list = list->next) - gnt_append_menu_action(tree, list->data, action); + gnt_append_menu_action(menu, list->data, action); } static void -append_proto_menu(GntTree *tree, GaimConnection *gc, GaimBlistNode *node) +append_proto_menu(GntMenu *menu, GaimConnection *gc, GaimBlistNode *node) { GList *list; GaimPluginProtocolInfo *prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); @@ -632,28 +645,21 @@ { GaimMenuAction *act = (GaimMenuAction *) list->data; act->data = node; - gnt_append_menu_action(tree, act, NULL); + gnt_append_menu_action(menu, act, NULL); } } static void -add_custom_action(GntTree *tree, const char *label, GaimCallback callback, +add_custom_action(GntMenu *menu, const char *label, GaimCallback callback, gpointer data) { GaimMenuAction *action = gaim_menu_action_new(label, callback, data, NULL); - gnt_append_menu_action(tree, action, NULL); - g_signal_connect_swapped(G_OBJECT(tree), "destroy", + gnt_append_menu_action(menu, action, NULL); + g_signal_connect_swapped(G_OBJECT(menu), "destroy", G_CALLBACK(gaim_menu_action_free), action); } static void -context_menu_toggle(GntTree *tree, GaimMenuAction *action, gpointer null) -{ - gboolean sel = gnt_tree_get_choice(tree, action); - gaim_blist_node_set_bool(action->data, "gnt-autojoin", sel); -} - -static void chat_components_edit_ok(GaimChat *chat, GaimRequestFields *allfields) { GList *groups, *fields; @@ -713,19 +719,26 @@ } static void -create_chat_menu(GntTree *tree, GaimChat *chat) +autojoin_toggled(GntMenuItem *item, gpointer data) +{ + GaimMenuAction *action = data; + gaim_blist_node_set_bool(action->data, "gnt-autojoin", + gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item))); +} + +static void +create_chat_menu(GntMenu *menu, GaimChat *chat) { GaimMenuAction *action = gaim_menu_action_new(_("Auto-join"), NULL, chat, NULL); - - gnt_tree_add_choice(tree, action, gnt_tree_create_row(tree, action->label), NULL, NULL); - gnt_tree_set_choice(tree, action, gaim_blist_node_get_bool((GaimBlistNode*)chat, "gnt-autojoin")); - - g_signal_connect_swapped(G_OBJECT(tree), "destroy", + GntMenuItem *check = gnt_menuitem_check_new(action->label); + gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(check), + gaim_blist_node_get_bool((GaimBlistNode*)chat, "gnt-autojoin")); + gnt_menu_add_item(menu, check); + gnt_menuitem_set_callback(check, autojoin_toggled, action); + g_signal_connect_swapped(G_OBJECT(menu), "destroy", G_CALLBACK(gaim_menu_action_free), action); - add_custom_action(tree, _("Edit Settings"), (GaimCallback)chat_components_edit, chat); - - g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(context_menu_toggle), NULL); + add_custom_action(menu, _("Edit Settings"), (GaimCallback)chat_components_edit, chat); } static void @@ -747,13 +760,13 @@ } static void -create_group_menu(GntTree *tree, GaimGroup *group) +create_group_menu(GntMenu *menu, GaimGroup *group) { - add_custom_action(tree, _("Add Buddy"), + add_custom_action(menu, _("Add Buddy"), GAIM_CALLBACK(gg_add_buddy), group); - add_custom_action(tree, _("Add Chat"), + add_custom_action(menu, _("Add Chat"), GAIM_CALLBACK(gg_add_chat), group); - add_custom_action(tree, _("Add Group"), + add_custom_action(menu, _("Add Group"), GAIM_CALLBACK(gg_add_group), group); } @@ -764,14 +777,14 @@ } static void -create_buddy_menu(GntTree *tree, GaimBuddy *buddy) +create_buddy_menu(GntMenu *menu, GaimBuddy *buddy) { GaimPluginProtocolInfo *prpl_info; prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(buddy->account->gc->prpl); if (prpl_info && prpl_info->get_info) { - add_custom_action(tree, _("Get Info"), + add_custom_action(menu, _("Get Info"), GAIM_CALLBACK(gg_blist_get_buddy_info_cb), buddy); } @@ -792,42 +805,23 @@ #endif /* Protocol actions */ - append_proto_menu(tree, + append_proto_menu(menu, gaim_account_get_connection(gaim_buddy_get_account(buddy)), (GaimBlistNode*)buddy); } static void -append_extended_menu(GntTree *tree, GaimBlistNode *node) +append_extended_menu(GntMenu *menu, GaimBlistNode *node) { GList *iter; for (iter = gaim_blist_node_get_extended_menu(node); iter; iter = g_list_delete_link(iter, iter)) { - gnt_append_menu_action(tree, iter->data, NULL); + gnt_append_menu_action(menu, iter->data, NULL); } } -static void -context_menu_callback(GntTree *tree, GGBlist *ggblist) -{ - GaimMenuAction *action = gnt_tree_get_selection_data(tree); - GaimBlistNode *node = ggblist->cnode; - - if (action) - { - void (*callback)(GaimBlistNode *, gpointer); - callback = (void (*)(GaimBlistNode *, gpointer))action->callback; - if (callback) - callback(action->data, node); - else - return; - } - - remove_context_menu(ggblist); -} - /* Xerox'd from gtkdialogs.c:gaim_gtkdialogs_remove_contact_cb */ static void remove_contact(GaimContact *contact) @@ -1007,79 +1001,71 @@ } static void +context_menu_destroyed(GntWidget *widget, GGBlist *ggblist) +{ + ggblist->context = NULL; +} + +static void draw_context_menu(GGBlist *ggblist) { GaimBlistNode *node = NULL; - GntWidget *context = NULL, *window = NULL; + GntWidget *context = NULL; GntTree *tree = NULL; int x, y, top, width; char *title = NULL; tree = GNT_TREE(ggblist->tree); - if (ggblist->context) - { - remove_context_menu(ggblist); - } - node = gnt_tree_get_selection_data(tree); if (ggblist->tooltip) remove_tooltip(ggblist); ggblist->cnode = node; - ggblist->context = context = gnt_tree_new(); - GNT_WIDGET_SET_FLAGS(context, GNT_WIDGET_NO_BORDER); - gnt_widget_set_name(context, "context menu"); - g_signal_connect(G_OBJECT(context), "activate", G_CALLBACK(context_menu_callback), ggblist); + + ggblist->context = context = gnt_menu_new(GNT_MENU_POPUP); + g_signal_connect(G_OBJECT(context), "destroy", G_CALLBACK(context_menu_destroyed), ggblist); if (!node) { - create_group_menu(GNT_TREE(context), NULL); + create_group_menu(GNT_MENU(context), NULL); title = g_strdup(_("Buddy List")); } else if (GAIM_BLIST_NODE_IS_CONTACT(node)) { - create_buddy_menu(GNT_TREE(context), + create_buddy_menu(GNT_MENU(context), gaim_contact_get_priority_buddy((GaimContact*)node)); title = g_strdup(gaim_contact_get_alias((GaimContact*)node)); } else if (GAIM_BLIST_NODE_IS_BUDDY(node)) { GaimBuddy *buddy = (GaimBuddy *)node; - create_buddy_menu(GNT_TREE(context), buddy); + create_buddy_menu(GNT_MENU(context), buddy); title = g_strdup(gaim_buddy_get_name(buddy)); } else if (GAIM_BLIST_NODE_IS_CHAT(node)) { GaimChat *chat = (GaimChat*)node; - create_chat_menu(GNT_TREE(context), chat); + create_chat_menu(GNT_MENU(context), chat); title = g_strdup(gaim_chat_get_name(chat)); } else if (GAIM_BLIST_NODE_IS_GROUP(node)) { GaimGroup *group = (GaimGroup *)node; - create_group_menu(GNT_TREE(context), group); + create_group_menu(GNT_MENU(context), group); title = g_strdup(group->name); } - append_extended_menu(GNT_TREE(context), node); + append_extended_menu(GNT_MENU(context), node); /* These are common for everything */ if (node) { - add_custom_action(GNT_TREE(context), _("Rename"), + add_custom_action(GNT_MENU(context), _("Rename"), GAIM_CALLBACK(gg_blist_rename_node_cb), node); - add_custom_action(GNT_TREE(context), _("Remove"), + add_custom_action(GNT_MENU(context), _("Remove"), GAIM_CALLBACK(gg_blist_remove_node_cb), node); if (ggblist->tagged && (GAIM_BLIST_NODE_IS_CONTACT(node) || GAIM_BLIST_NODE_IS_GROUP(node))) { - add_custom_action(GNT_TREE(context), _("Place tagged"), + add_custom_action(GNT_MENU(context), _("Place tagged"), GAIM_CALLBACK(gg_blist_place_tagged), node); } else if (GAIM_BLIST_NODE_IS_BUDDY(node)) { - add_custom_action(GNT_TREE(context), _("Tag"), + add_custom_action(GNT_MENU(context), _("Tag"), GAIM_CALLBACK(gg_blist_tag_buddy), node); } } - window = gnt_vbox_new(FALSE); - GNT_WIDGET_SET_FLAGS(window, GNT_WIDGET_TRANSIENT); - gnt_box_set_toplevel(GNT_BOX(window), TRUE); - gnt_box_set_title(GNT_BOX(window), title); - - gnt_widget_set_size(context, 0, g_list_length(GNT_TREE(context)->list)); - gnt_box_add_widget(GNT_BOX(window), context); - /* Set the position for the popup */ gnt_widget_get_position(GNT_WIDGET(tree), &x, &y); gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL); @@ -1088,8 +1074,8 @@ x += width; y += top - 1; - gnt_widget_set_position(window, x, y); - gnt_widget_draw(window); + gnt_widget_set_position(context, x, y); + gnt_screen_menu_show(GNT_MENU(context)); g_free(title); } @@ -1151,9 +1137,6 @@ if (!gnt_widget_has_focus(ggblist->tree)) return; - if (ggblist->context) - return; - if (ggblist->tooltip) { /* XXX: Once we can properly redraw on expose events, this can be removed at the end @@ -1252,8 +1235,6 @@ static void selection_changed(GntWidget *widget, gpointer old, gpointer current, GGBlist *ggblist) { - if (ggblist->context) - remove_context_menu(ggblist); draw_tooltip(ggblist); } @@ -1276,12 +1257,6 @@ ret = TRUE; } - if (ggblist->context) - { - ret = gnt_widget_key_pressed(ggblist->context, text); - stop = TRUE; - } - if (strcmp(text, GNT_KEY_CTRL_O) == 0) { gaim_prefs_set_bool(PREF_ROOT "/showoffline", @@ -1336,7 +1311,7 @@ if (ggblist->tooltip) remove_tooltip(ggblist); else if (ggblist->context) - remove_context_menu(ggblist); + gnt_widget_destroy(ggblist->context); } static void diff -r 852803694be3 -r 97977138cf29 console/libgnt/Makefile.am --- a/console/libgnt/Makefile.am Sat Oct 28 20:38:25 2006 +0000 +++ b/console/libgnt/Makefile.am Sat Oct 28 22:14:52 2006 +0000 @@ -18,6 +18,7 @@ gntmarshal.c \ gntmenu.c \ gntmenuitem.c \ + gntmenuitemcheck.c \ gntstyle.c \ gnttextview.c \ gnttree.c \ @@ -39,6 +40,7 @@ gntmarshal.h \ gntmenu.h \ gntmenuitem.h \ + gntmenuitemcheck.h \ gntstyle.h \ gnttextview.h \ gnttree.h \ diff -r 852803694be3 -r 97977138cf29 console/libgnt/gntmenu.c --- a/console/libgnt/gntmenu.c Sat Oct 28 20:38:25 2006 +0000 +++ b/console/libgnt/gntmenu.c Sat Oct 28 22:14:52 2006 +0000 @@ -1,4 +1,5 @@ #include "gntmenu.h" +#include "gntmenuitemcheck.h" #include @@ -60,8 +61,14 @@ static void menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent) { - gnt_tree_add_row_last(GNT_TREE(menu), item, - gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent); + if (GNT_IS_MENUITEM_CHECK(item)) { + gnt_tree_add_choice(GNT_TREE(menu), item, + gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL); + gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item))); + } else + gnt_tree_add_row_last(GNT_TREE(menu), item, + gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent); + if (0 && item->submenu) { GntMenu *sub = GNT_MENU(item->submenu); GList *iter; @@ -126,8 +133,6 @@ int current = menu->selected; if (menu->submenu) { - /*if (gnt_widget_key_pressed(GNT_WIDGET(menu->submenu), text))*/ - /*return TRUE;*/ return (gnt_widget_key_pressed(GNT_WIDGET(menu->submenu), text)); } @@ -178,6 +183,21 @@ } static void +gnt_menu_toggled(GntTree *tree, gpointer key) +{ + GntMenuItem *item = GNT_MENUITEM(key); + GntMenu *menu = GNT_MENU(tree); + gboolean check = gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)); + gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item), !check); + if (item->callback) + item->callback(item, item->callbackdata); + while (menu) { + gnt_widget_hide(GNT_WIDGET(menu)); + menu = menu->parentmenu; + } +} + +static void gnt_menu_activate(GntWidget *widget) { GntMenu *menu = GNT_MENU(widget); @@ -189,8 +209,12 @@ item = gnt_tree_get_selection_data(GNT_TREE(menu)); } - if (item) - menuitem_activate(menu, item); + if (item) { + if (GNT_MENUITEM_CHECK(item)) + gnt_menu_toggled(GNT_TREE(widget), item); + else + menuitem_activate(menu, item); + } } static void @@ -220,6 +244,8 @@ wid_class->activate = gnt_menu_activate; wid_class->hide = gnt_menu_hide; + parent_class->toggled = gnt_menu_toggled; + GNTDEBUG; } diff -r 852803694be3 -r 97977138cf29 console/libgnt/gntmenuitem.h --- a/console/libgnt/gntmenuitem.h Sat Oct 28 20:38:25 2006 +0000 +++ b/console/libgnt/gntmenuitem.h Sat Oct 28 22:14:52 2006 +0000 @@ -19,6 +19,8 @@ typedef struct _GnMenuItemPriv GntMenuItemPriv; typedef struct _GnMenuItemClass GntMenuItemClass; +#include "gntmenu.h" + struct _GnMenuItemPriv { /* These will be used to determine the position of the submenu */ diff -r 852803694be3 -r 97977138cf29 console/libgnt/gntmenuitemcheck.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntmenuitemcheck.c Sat Oct 28 22:14:52 2006 +0000 @@ -0,0 +1,67 @@ +#include "gntmenuitemcheck.h" + +static GntMenuItemClass *parent_class = NULL; + +static void +gnt_menuitem_check_class_init(GntMenuItemCheckClass *klass) +{ + parent_class = GNT_MENUITEM_CLASS(klass); + + GNTDEBUG; +} + +static void +gnt_menuitem_check_init(GTypeInstance *instance, gpointer class) +{ + GNTDEBUG; +} + +/****************************************************************************** + * GntMenuItemCheck API + *****************************************************************************/ +GType +gnt_menuitem_check_get_gtype(void) +{ + static GType type = 0; + + if(type == 0) + { + static const GTypeInfo info = { + sizeof(GntMenuItemCheckClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)gnt_menuitem_check_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(GntMenuItemCheck), + 0, /* n_preallocs */ + gnt_menuitem_check_init, /* instance_init */ + }; + + type = g_type_register_static(GNT_TYPE_MENUITEM, + "GntMenuItemCheck", + &info, 0); + } + + return type; +} + +GntMenuItem *gnt_menuitem_check_new(const char *text) +{ + GntMenuItem *item = g_object_new(GNT_TYPE_MENUITEM_CHECK, NULL); + GntMenuItem *menuitem = GNT_MENUITEM(item); + + menuitem->text = g_strdup(text); + return item; +} + +gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item) +{ + return item->checked; +} + +void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set) +{ + item->checked = set; +} + diff -r 852803694be3 -r 97977138cf29 console/libgnt/gntmenuitemcheck.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/console/libgnt/gntmenuitemcheck.h Sat Oct 28 22:14:52 2006 +0000 @@ -0,0 +1,52 @@ +#ifndef GNT_MENUITEM_CHECK_H +#define GNT_MENUITEM_CHECK_H + +#include "gnt.h" +#include "gntcolors.h" +#include "gntkeys.h" +#include "gntmenuitem.h" + +#define GNT_TYPE_MENUITEM_CHECK (gnt_menuitem_check_get_gtype()) +#define GNT_MENUITEM_CHECK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheck)) +#define GNT_MENUITEM_CHECK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass)) +#define GNT_IS_MENUITEM_CHECK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNT_TYPE_MENUITEM_CHECK)) +#define GNT_IS_MENUITEM_CHECK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_MENUITEM_CHECK)) +#define GNT_MENUITEM_CHECK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_MENUITEM_CHECK, GntMenuItemCheckClass)) + +#define GNT_MENUITEM_CHECK_FLAGS(obj) (GNT_MENUITEM_CHECK(obj)->priv.flags) +#define GNT_MENUITEM_CHECK_SET_FLAGS(obj, flags) (GNT_MENUITEM_CHECK_FLAGS(obj) |= flags) +#define GNT_MENUITEM_CHECK_UNSET_FLAGS(obj, flags) (GNT_MENUITEM_CHECK_FLAGS(obj) &= ~(flags)) + +typedef struct _GnMenuItemCheck GntMenuItemCheck; +typedef struct _GnMenuItemCheckPriv GntMenuItemCheckPriv; +typedef struct _GnMenuItemCheckClass GntMenuItemCheckClass; + +struct _GnMenuItemCheck +{ + GntMenuItem parent; + gboolean checked; +}; + +struct _GnMenuItemCheckClass +{ + GntMenuItemClass parent; + + void (*gnt_reserved1)(void); + void (*gnt_reserved2)(void); + void (*gnt_reserved3)(void); + void (*gnt_reserved4)(void); +}; + +G_BEGIN_DECLS + +GType gnt_menuitem_check_get_gtype(void); + +GntMenuItem *gnt_menuitem_check_new(const char *text); + +gboolean gnt_menuitem_check_get_checked(GntMenuItemCheck *item); + +void gnt_menuitem_check_set_checked(GntMenuItemCheck *item, gboolean set); + +G_END_DECLS + +#endif /* GNT_MENUITEM_CHECK_H */ diff -r 852803694be3 -r 97977138cf29 console/libgnt/gnttree.c --- a/console/libgnt/gnttree.c Sat Oct 28 20:38:25 2006 +0000 +++ b/console/libgnt/gnttree.c Sat Oct 28 22:14:52 2006 +0000 @@ -691,7 +691,7 @@ g_signal_new("toggled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, - 0, + G_STRUCT_OFFSET(GntTreeClass, toggled), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); diff -r 852803694be3 -r 97977138cf29 console/libgnt/gnttree.h --- a/console/libgnt/gnttree.h Sat Oct 28 20:38:25 2006 +0000 +++ b/console/libgnt/gnttree.h Sat Oct 28 22:14:52 2006 +0000 @@ -56,6 +56,7 @@ GntWidgetClass parent; void (*selection_changed)(GntTreeRow *old, GntTreeRow * current); + void (*toggled)(GntTree *tree, gpointer key); void (*gnt_reserved1)(void); void (*gnt_reserved2)(void); diff -r 852803694be3 -r 97977138cf29 console/plugins/gntgf.c --- a/console/plugins/gntgf.c Sat Oct 28 20:38:25 2006 +0000 +++ b/console/plugins/gntgf.c Sat Oct 28 22:14:52 2006 +0000 @@ -354,8 +354,8 @@ "gntgf", N_("GntGf"), VERSION, - N_("Toaster plugin for GntGaim."), - N_("Toaster plugin for GntGaim."), + N_("Toaster plugin for Gaim-Text."), + N_("Toaster plugin for Gaim-Text."), "Sadrul H Chowdhury ", "http://gaim.sourceforge.net", plugin_load,