diff options
Diffstat (limited to 'libdbusmenu-gtk/menu.c')
-rw-r--r-- | libdbusmenu-gtk/menu.c | 143 |
1 files changed, 60 insertions, 83 deletions
diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c index dd2df37..bc7458c 100644 --- a/libdbusmenu-gtk/menu.c +++ b/libdbusmenu-gtk/menu.c @@ -1,3 +1,31 @@ +/* +A library to take the object model made consistent by libdbusmenu-glib +and visualize it in GTK. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of either or both of the following licenses: + +1) the GNU Lesser General Public License version 3, as published by the +Free Software Foundation; and/or +2) the GNU Lesser General Public License version 2.1, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR +PURPOSE. See the applicable version of the GNU Lesser General Public +License for more details. + +You should have received a copy of both the GNU Lesser General Public +License version 3 and version 2.1 along with this program. If not, see +<http://www.gnu.org/licenses/> +*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -6,6 +34,7 @@ #include "menu.h" #include "libdbusmenu-glib/client.h" +#include "client.h" /* Properties */ enum { @@ -17,7 +46,7 @@ enum { /* Private */ typedef struct _DbusmenuGtkMenuPrivate DbusmenuGtkMenuPrivate; struct _DbusmenuGtkMenuPrivate { - DbusmenuClient * client; + DbusmenuGtkClient * client; gchar * dbus_object; gchar * dbus_name; @@ -155,114 +184,62 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec) /* Internal Functions */ -static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem"; -static const gchar * data_menu = "dbusmenugtk-data-gtkmenu"; - -static gboolean -menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi) -{ - dbusmenu_menuitem_activate(mi); - return TRUE; -} - static void -menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, GtkMenuItem * gmi) +root_child_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, DbusmenuGtkMenu * menu) { - if (!g_strcmp0(prop, "label")) { - gtk_menu_item_set_label(gmi, value); - gtk_widget_show(GTK_WIDGET(gmi)); - } - + g_debug("Root new child"); + DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); + gtk_menu_shell_insert(GTK_MENU_SHELL(menu), GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)), position); + gtk_widget_show(GTK_WIDGET(menu)); return; } static void -destoryed_dbusmenuitem_cb (gpointer udata, GObject * dbusmenuitem) +root_child_moved (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint newposition, guint oldposition, DbusmenuGtkMenu * menu) { - /* g_debug("DbusmenuMenuitem was destroyed"); */ - gtk_widget_destroy(GTK_WIDGET(udata)); + g_debug("Root child moved"); + DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); + gtk_menu_reorder_child(GTK_MENU(menu), GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)), newposition); return; } static void -connect_menuitem (DbusmenuMenuitem * mi, GtkMenuItem * gmi) +root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGtkMenu * menu) { - g_object_set_data(G_OBJECT(mi), data_menuitem, gmi); - - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi); - g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), mi); - - g_object_weak_ref(G_OBJECT(mi), destoryed_dbusmenuitem_cb, gmi); - + g_debug("Root child deleted"); + if (g_list_length(dbusmenu_menuitem_get_children(root)) == 0) { + gtk_widget_hide(GTK_WIDGET(menu)); + } return; } static void -process_dbusmenu_menuitem (DbusmenuMenuitem * mi, GtkMenu * parentmenu) -{ - gpointer unknown_menuitem = g_object_get_data(G_OBJECT(mi), data_menuitem); - if (unknown_menuitem == NULL) { - /* Oh, a virgin DbusmenuMenuitem, let's fix that. */ - GtkWidget * menuitem = gtk_menu_item_new(); - connect_menuitem(mi, GTK_MENU_ITEM(menuitem)); - unknown_menuitem = menuitem; - gtk_menu_shell_append(GTK_MENU_SHELL(parentmenu), menuitem); - } - - GList * children = dbusmenu_menuitem_get_children(mi); - if (children == NULL) { - /* If there are no children to process we are - done and we can move along */ +root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) { + if (newroot == NULL) { + gtk_widget_hide(GTK_WIDGET(menu)); return; } - /* Phase 0: Make a submenu if we don't have one */ - gpointer unknown_menu = g_object_get_data(G_OBJECT(mi), data_menu); - if (unknown_menu == NULL) { - GtkWidget * gtkmenu = gtk_menu_new(); - g_object_ref(gtkmenu); - g_object_set_data_full(G_OBJECT(mi), data_menu, gtkmenu, g_object_unref); - unknown_menu = gtkmenu; - gtk_menu_item_set_submenu(GTK_MENU_ITEM(unknown_menuitem), gtkmenu); - gtk_widget_show(gtkmenu); - } + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(root_child_added), menu); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(root_child_moved), menu); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(root_child_delete), menu); - /* Phase 1: Add missing children */ GList * child = NULL; - for (child = children; child != NULL; child = g_list_next(child)) { - process_dbusmenu_menuitem(DBUSMENU_MENUITEM(child->data), GTK_MENU(unknown_menu)); + guint count = 0; + for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child)) { + gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(client, child->data))); + count++; } - /* Phase 2: Delete removed children */ - /* Actually, we don't need to do this because of the weak - reference that we've added above. When the DbusmenuMenuitem - gets destroyed it takes its GtkMenuItem with it. Bye bye. */ - - /* Phase 3: Profit! */ - return; -} - -/* Processing the layout being updated and handling - that and making it into a menu */ -static void -process_layout_change (DbusmenuClient * client, DbusmenuGtkMenu * gtkmenu) -{ - DbusmenuMenuitem * root = dbusmenu_client_get_root(client); - - GList * children = dbusmenu_menuitem_get_children(root); - if (children == NULL) { - return; - } - - GList * child = NULL; - for (child = children; child != NULL; child = g_list_next(child)) { - process_dbusmenu_menuitem(DBUSMENU_MENUITEM(child->data), GTK_MENU(gtkmenu)); + if (count > 0) { + gtk_widget_show(GTK_WIDGET(menu)); + } else { + gtk_widget_hide(GTK_WIDGET(menu)); } return; } - /* Builds the client and connects all of the signals up for it so that it's happy-happy */ static void @@ -271,11 +248,11 @@ build_client (DbusmenuGtkMenu * self) DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(self); if (priv->client == NULL) { - priv->client = dbusmenu_client_new(priv->dbus_name, priv->dbus_object); + priv->client = dbusmenu_gtkclient_new(priv->dbus_name, priv->dbus_object); /* Register for layout changes, this should come after the creation of the client pulls it from DBus */ - g_signal_connect(G_OBJECT(priv->client), DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED, G_CALLBACK(process_layout_change), self); + g_signal_connect(G_OBJECT(priv->client), DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(root_changed), self); } return; |