diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2013-03-26 15:05:06 -0500 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2013-03-26 15:05:06 -0500 |
commit | bf3b14f5c5105c63816b9555dffb3bf3e273c602 (patch) | |
tree | 5b11af94ad6879abc5e7a2ac92ae6e1b769f76a7 | |
parent | 27f3661cfb2266ee87a552738e5c03774dc9ae68 (diff) | |
download | ayatana-ido-bf3b14f5c5105c63816b9555dffb3bf3e273c602.tar.gz ayatana-ido-bf3b14f5c5105c63816b9555dffb3bf3e273c602.tar.bz2 ayatana-ido-bf3b14f5c5105c63816b9555dffb3bf3e273c602.zip |
add user-widget.[ch] from indicator-session's trunk
-rw-r--r-- | src/user-widget.c | 292 | ||||
-rw-r--r-- | src/user-widget.h | 55 |
2 files changed, 347 insertions, 0 deletions
diff --git a/src/user-widget.c b/src/user-widget.c new file mode 100644 index 0000000..79b87b0 --- /dev/null +++ b/src/user-widget.c @@ -0,0 +1,292 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + Mirco Müller <mirco.mueller@canonical.com> + Charles Kerr <charles.kerr@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, 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 GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include <gtk/gtk.h> + +#include <libindicator/indicator-image-helper.h> + +#include "shared-names.h" +#include "user-widget.h" + + +typedef struct _UserWidgetPrivate UserWidgetPrivate; + +struct _UserWidgetPrivate +{ + DbusmenuMenuitem* twin_item; + GtkWidget* user_image; + GtkWidget* user_name; + GtkWidget* container; + GtkWidget* tick_icon; + gboolean logged_in; + gboolean sessions_active; +}; + +#define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate)) + +/* Prototypes */ +static void user_widget_class_init (UserWidgetClass *klass); +static void user_widget_init (UserWidget *self); +static void user_widget_dispose (GObject *object); +static void user_widget_finalize (GObject *object); + +static void user_widget_set_twin_item (UserWidget* self, + DbusmenuMenuitem* twin_item); + +static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image, + cairo_t* cr, + gpointer user_data); + +G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM); + +static void +user_widget_class_init (UserWidgetClass *klass) +{ + GObjectClass * gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (UserWidgetPrivate)); + + gobject_class->dispose = user_widget_dispose; + gobject_class->finalize = user_widget_finalize; +} + +static void +user_widget_init (UserWidget *self) +{ + self->priv = USER_WIDGET_GET_PRIVATE(self); + + UserWidgetPrivate * priv = self->priv; + + priv->user_image = NULL; + priv->user_name = NULL; + priv->logged_in = FALSE; + priv->sessions_active = FALSE; + priv->container = NULL; + priv->tick_icon = NULL; + + // Create the UI elements. + priv->user_image = gtk_image_new (); + gtk_misc_set_alignment(GTK_MISC(priv->user_image), 0.0, 0.0); + + priv->user_name = gtk_label_new (NULL); + + priv->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + + priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in", + GTK_ICON_SIZE_MENU); + gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5); + + // Pack it together + gtk_box_pack_start (GTK_BOX (priv->container), + priv->user_image, + FALSE, + FALSE, + 0); + gtk_box_pack_start (GTK_BOX (priv->container), + priv->user_name, + FALSE, + FALSE, + 3); + gtk_box_pack_end (GTK_BOX(priv->container), + priv->tick_icon, + FALSE, + FALSE, 5); + + gtk_widget_show_all (priv->container); + gtk_container_add (GTK_CONTAINER (self), priv->container); + gtk_widget_show_all (priv->tick_icon); + gtk_widget_set_no_show_all (priv->tick_icon, TRUE); + gtk_widget_hide (priv->tick_icon); + + + // Fetch the drawing context. + g_signal_connect_after (GTK_WIDGET(self), "draw", + G_CALLBACK(user_widget_primitive_draw_cb_gtk_3), + GTK_WIDGET(self)); +} + +static void +user_widget_dispose (GObject *object) +{ + G_OBJECT_CLASS (user_widget_parent_class)->dispose (object); +} + +// TODO tidy up image and name +static void +user_widget_finalize (GObject *object) +{ + G_OBJECT_CLASS (user_widget_parent_class)->finalize (object); +} + + +/*****************************************************************/ + +// TODO handle drawing of green check mark +static gboolean +user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget, + cairo_t* cr, + gpointer user_data) +{ + g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); + UserWidget* meta = USER_WIDGET(user_data); + UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + + // Draw dot only when user is the current user. + if (dbusmenu_menuitem_property_get_bool (priv->twin_item, USER_ITEM_PROP_IS_CURRENT_USER)) + { + gdouble x, y; + GtkStyle * style = gtk_widget_get_style (widget); + + GtkAllocation allocation; + gtk_widget_get_allocation (widget, &allocation); + x = allocation.x + 13; + y = allocation.height / 2; + + cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI); + + cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, + style->fg[gtk_widget_get_state(widget)].green/65535.0, + style->fg[gtk_widget_get_state(widget)].blue/65535.0); + cairo_fill (cr); + } + + return FALSE; +} + +/*** +**** +***/ + +static void +update_icon (UserWidget * self, DbusmenuMenuitem * mi) +{ + gboolean updated = FALSE; + GtkImage * image = GTK_IMAGE(self->priv->user_image); + + /* first try the menuitem's icon property */ + const gchar * icon_name = dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_ICON); + if (icon_name != NULL) + { + int width = 18; /* arbitrary default values */ + int height = 18; + GError * err = NULL; + GdkPixbuf * pixbuf = NULL; + + /* load the image */ + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height); + pixbuf = gdk_pixbuf_new_from_file_at_size (icon_name, width, height, &err); + if (err == NULL) + { + gtk_image_set_from_pixbuf (image, pixbuf); + g_object_unref (pixbuf); + updated = TRUE; + } + else + { + g_warning ("Couldn't load the image \"%s\": %s", icon_name, err->message); + g_clear_error (&err); + } + } + + /* as a fallback, use the default user icon */ + if (!updated) + { + gtk_image_set_from_icon_name (image, + USER_ITEM_ICON_DEFAULT, + GTK_ICON_SIZE_MENU); + } +} + +static void +update_logged_in (UserWidget * self, DbusmenuMenuitem * mi) +{ + const gboolean b = dbusmenu_menuitem_property_get_bool (mi, USER_ITEM_PROP_LOGGED_IN); + + g_debug ("User \"%s\" %s active sessions", + dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME), + b ? "has" : "doesn't have"); + + gtk_widget_set_visible (self->priv->tick_icon, b); +} + +static void +update_name (UserWidget * self, DbusmenuMenuitem * mi) +{ + gtk_label_set_label (GTK_LABEL(self->priv->user_name), + dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME)); +} + +static void +user_widget_property_update (DbusmenuMenuitem * mi, + const gchar * property, + GVariant * value, + UserWidget * self) +{ + g_return_if_fail (IS_USER_WIDGET (self)); + + if (!g_strcmp0 (property, USER_ITEM_PROP_LOGGED_IN)) + { + update_logged_in (self, mi); + } + else if (!g_strcmp0 (property, USER_ITEM_PROP_ICON)) + { + update_icon (self, mi); + } + else if (!g_strcmp0 (property, USER_ITEM_PROP_NAME)) + { + update_name (self, mi); + } + else + { + g_debug ("%s FIXME: unhandled property change %s", G_STRFUNC, property); + } +} + +static void +user_widget_set_twin_item (UserWidget * self, DbusmenuMenuitem * mi) +{ + self->priv->twin_item = mi; + + update_icon (self, mi); + update_name (self, mi); + update_logged_in (self, mi); + + g_signal_connect (G_OBJECT(mi), "property-changed", + G_CALLBACK(user_widget_property_update), self); +} + + /** + * user_widget_new: + * @item: the #DbusmenuMenuitem this widget will render. + * + * Returns: (transfer full): a new #UserWidget. + **/ +GtkWidget* +user_widget_new (DbusmenuMenuitem *item) +{ + GtkWidget* widget = g_object_new(USER_WIDGET_TYPE, NULL); + user_widget_set_twin_item ( USER_WIDGET(widget), item ); + return widget; +} diff --git a/src/user-widget.h b/src/user-widget.h new file mode 100644 index 0000000..0953e6c --- /dev/null +++ b/src/user-widget.h @@ -0,0 +1,55 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, 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 GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __USER_WIDGET_H__ +#define __USER_WIDGET_H__ + +#include <gtk/gtk.h> +#include <libdbusmenu-gtk/menuitem.h> + +G_BEGIN_DECLS + +#define USER_WIDGET_TYPE (user_widget_get_type ()) +#define USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_WIDGET_TYPE, UserWidget)) +#define USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), USER_WIDGET_TYPE, UserWidgetClass)) +#define IS_USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_WIDGET_TYPE)) +#define IS_USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_WIDGET_TYPE)) +#define USER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_WIDGET_TYPE, UserWidgetClass)) + +typedef struct _UserWidget UserWidget; +typedef struct _UserWidgetClass UserWidgetClass; +typedef struct _UserWidgetPrivate UserWidgetPrivate; + +struct _UserWidgetClass +{ + GtkMenuItemClass parent_class; +}; + +struct _UserWidget +{ + /*< private >*/ + GtkMenuItem parent; + UserWidgetPrivate * priv; +}; + +GType user_widget_get_type (void) G_GNUC_CONST; +GtkWidget* user_widget_new(DbusmenuMenuitem *twin_item); + +G_END_DECLS + +#endif |