aboutsummaryrefslogtreecommitdiff
path: root/src/user-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/user-widget.c')
-rw-r--r--src/user-widget.c509
1 files changed, 442 insertions, 67 deletions
diff --git a/src/user-widget.c b/src/user-widget.c
index 6495e80..937a9eb 100644
--- a/src/user-widget.c
+++ b/src/user-widget.c
@@ -3,7 +3,8 @@ Copyright 2011 Canonical Ltd.
Authors:
Conor Curran <conor.curran@canonical.com>
-
+ Mirco Müller <mirco.mueller@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.
@@ -24,6 +25,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <glib.h>
+#include <math.h>
#include <libindicator/indicator-image-helper.h>
#include "user-widget.h"
#include "dbus-shared-names.h"
@@ -35,6 +37,7 @@ struct _UserWidgetPrivate
{
DbusmenuMenuitem* twin_item;
GtkWidget* user_image;
+ gboolean using_personal_icon;
GtkWidget* user_name;
GtkWidget* container;
GtkWidget* tick_icon;
@@ -44,6 +47,13 @@ struct _UserWidgetPrivate
#define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate))
+typedef struct
+{
+ double r;
+ double g;
+ double b;
+} CairoColorRGB;
+
/* Prototypes */
static void user_widget_class_init (UserWidgetClass *klass);
static void user_widget_init (UserWidget *self);
@@ -60,14 +70,30 @@ static void user_widget_property_update (DbusmenuMenuitem* item,
gchar* property,
GVariant* value,
gpointer userdata);
+
+
+static void _color_shade (const CairoColorRGB *a,
+ float k,
+ CairoColorRGB *b);
+
+static void draw_album_border (GtkWidget *widget, gboolean selected);
+
#if GTK_CHECK_VERSION(3, 0, 0)
static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image,
cairo_t* cr,
gpointer user_data);
+static gboolean user_widget_draw_usericon_gtk_3 (GtkWidget *widget,
+ cairo_t* cr,
+ gpointer user_data);
+
#else
static gboolean user_widget_primitive_draw_cb (GtkWidget *image,
GdkEventExpose *event,
gpointer user_data);
+static gboolean user_widget_draw_usericon_gtk_2 (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data);
+
#endif
G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM);
@@ -106,24 +132,9 @@ user_widget_init (UserWidget *self)
// Create the UI elements.
priv->user_image = gtk_image_new ();
+ gtk_misc_set_alignment(GTK_MISC(priv->user_image), 0.0, 0.0);
+ gtk_misc_set_padding (GTK_MISC(priv->user_image),0, 4.0);
- // Just for now set the image to the default avator image
- GdkPixbuf* pixbuf = NULL;
- GError* error = NULL;
- pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
- "avatar-default",
- 32,
- GTK_ICON_LOOKUP_FORCE_SIZE,
- &error);
-
- if (pixbuf == NULL || error != NULL) {
- g_warning ("Could not load the default avatar image for some reason");
- }
- else{
- gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf);
- g_object_unref (pixbuf);
- }
-
priv->user_name = gtk_label_new ("");
priv->container = gtk_hbox_new (FALSE, 0);
priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in",
@@ -146,30 +157,36 @@ user_widget_init (UserWidget *self)
FALSE,
FALSE, 5);
- gtk_widget_show_all (priv->container);
- gtk_container_add (GTK_CONTAINER (self), priv->container);
-
+ 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.
#if GTK_CHECK_VERSION(3, 0, 0)
g_signal_connect_after (GTK_WIDGET(self), "draw",
G_CALLBACK(user_widget_primitive_draw_cb_gtk_3),
GTK_WIDGET(self));
+
+ g_signal_connect_after (GTK_WIDGET(priv->user_image), "draw",
+ G_CALLBACK(user_widget_draw_usericon_gtk_3),
+ GTK_WIDGET(self));
+
#else
g_signal_connect_after (GTK_WIDGET(self), "expose-event",
G_CALLBACK(user_widget_primitive_draw_cb),
GTK_WIDGET(self));
+ g_signal_connect_after (GTK_WIDGET(priv->user_image), "expose-event",
+ G_CALLBACK(user_widget_draw_usericon_gtk_2),
+ GTK_WIDGET(self));
#endif
}
static void
user_widget_dispose (GObject *object)
{
- //UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(USER_WIDGET(object));
-
G_OBJECT_CLASS (user_widget_parent_class)->dispose (object);
}
@@ -180,9 +197,11 @@ user_widget_finalize (GObject *object)
G_OBJECT_CLASS (user_widget_parent_class)->finalize (object);
}
+
+/*****************************************************************/
+
#if GTK_CHECK_VERSION(3, 0, 0)
-// Draw the radio dot and/or green check mark
// TODO handle drawing of green check mark
static gboolean
user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
@@ -201,15 +220,13 @@ user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
}
GtkStyle *style;
- gdouble x, y;
- gdouble offset = 15.0;
-
+ gdouble x, y;
style = gtk_widget_get_style (widget);
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
x = allocation.x + 13;
- y = offset;
+ y = allocation.height / 2;
cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);;
@@ -221,68 +238,381 @@ user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
return FALSE;
}
+static gboolean
+user_widget_draw_usericon_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);
+
+ if (priv->using_personal_icon == FALSE)
+ return FALSE;
+
+ draw_album_border (widget, FALSE);
+ return FALSE;
+}
+/**
+ * TODO:
+ * Sort out gtk2
+ */
// GTK 2 Expose handler
#else
-// Draw the triangle if the player is running ...
+static gboolean
+user_widget_draw_usericon_gtk_2 (GtkWidget *widget,
+ GdkEventExpose *event,
+ 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);
+
+ if (priv->using_personal_icon == FALSE)
+ return FALSE;
+
+ draw_album_border (widget, FALSE);
+ return FALSE;
+}
+
static gboolean
user_widget_primitive_draw_cb (GtkWidget *widget,
GdkEventExpose *event,
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)){
+ return FALSE;
+ }
+
GtkStyle *style;
cairo_t *cr;
- int x, y, arrow_width, arrow_height;
-
- gint offset = 3;
- arrow_width = 5;
- arrow_height = 9;
+ cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
+ gdouble x, y;
style = gtk_widget_get_style (widget);
- cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
-
GtkAllocation allocation;
+
gtk_widget_get_allocation (widget, &allocation);
- x = allocation.x;
- y = allocation.y;
-
- // Draw player icon
- if (priv->icon_buf != NULL){
- gdk_cairo_set_source_pixbuf (cr,
- priv->icon_buf,
- x + arrow_width + 1,
- y + offset);
- cairo_paint (cr);
- }
-
- // Draw triangle but only if the player is running.
- if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){
- y += (double)arrow_height/2.0 + offset;
- cairo_set_line_width (cr, 1.0);
-
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x, y + arrow_height);
- cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
- cairo_close_path (cr);
- 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);
- }
+ x = allocation.x + 13;
+ y = allocation.y + allocation.height/2;
+
+ cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);;
- cairo_destroy (cr);*/
+ 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);
+ cairo_destroy (cr);
+
return FALSE;
}
#endif
+static void
+draw_album_border(GtkWidget *widg, gboolean selected)
+{
+ cairo_t *cr;
+ cr = gdk_cairo_create (gtk_widget_get_window (widg));
+ #if GTK_CHECK_VERSION(3, 0, 0)
+ gtk_style_context_add_class (gtk_widget_get_style_context (widg),
+ "menu");
+ #endif
+
+ GtkStyle *style;
+ style = gtk_widget_get_style (widg);
+
+ GtkAllocation alloc;
+ gtk_widget_get_allocation (widg, &alloc);
+ gint offset = 0;
+ gint v_offset = 4;
+
+ alloc.width = alloc.width + (offset * 2);
+ alloc.height = alloc.height - v_offset - 2;
+ alloc.x = alloc.x - offset;
+ alloc.y = alloc.y + v_offset/2 +1;
+
+ CairoColorRGB bg_normal, fg_normal;
+
+ bg_normal.r = style->bg[0].red/65535.0;
+ bg_normal.g = style->bg[0].green/65535.0;
+ bg_normal.b = style->bg[0].blue/65535.0;
+
+ gint state = selected ? 5 : 0;
+
+ fg_normal.r = style->fg[state].red/65535.0;
+ fg_normal.g = style->fg[state].green/65535.0;
+ fg_normal.b = style->fg[state].blue/65535.0;
+
+ CairoColorRGB dark_top_color;
+ CairoColorRGB light_bottom_color;
+ CairoColorRGB background_color;
+
+ _color_shade ( &bg_normal, 0.93, &background_color );
+ _color_shade ( &bg_normal, 0.23, &dark_top_color );
+ _color_shade ( &fg_normal, 0.55, &light_bottom_color );
+
+ cairo_rectangle (cr,
+ alloc.x, alloc.y,
+ alloc.width, alloc.height);
+
+ cairo_set_line_width (cr, 1.0);
+
+ cairo_clip ( cr );
+
+ cairo_move_to (cr, alloc.x, alloc.y );
+ cairo_line_to (cr, alloc.x + alloc.width,
+ alloc.y );
+ cairo_line_to ( cr, alloc.x + alloc.width,
+ alloc.y + alloc.height );
+ cairo_line_to ( cr, alloc.x, alloc.y + alloc.height );
+ cairo_line_to ( cr, alloc.x, alloc.y);
+ cairo_close_path (cr);
+
+ cairo_set_source_rgba ( cr,
+ background_color.r,
+ background_color.g,
+ background_color.b,
+ 1.0 );
+
+ cairo_stroke ( cr );
+
+ cairo_move_to (cr, alloc.x, alloc.y );
+ cairo_line_to (cr, alloc.x + alloc.width,
+ alloc.y );
+
+ cairo_close_path (cr);
+ cairo_set_source_rgba ( cr,
+ dark_top_color.r,
+ dark_top_color.g,
+ dark_top_color.b,
+ 1.0 );
+
+ cairo_stroke ( cr );
+
+ cairo_move_to ( cr, alloc.x + alloc.width,
+ alloc.y + alloc.height );
+ cairo_line_to ( cr, alloc.x, alloc.y + alloc.height );
+
+ cairo_close_path (cr);
+ cairo_set_source_rgba ( cr,
+ light_bottom_color.r,
+ light_bottom_color.g,
+ light_bottom_color.b,
+ 1.0);
+
+ cairo_stroke ( cr );
+ cairo_destroy (cr);
+}
+
+static void
+_color_rgb_to_hls (gdouble *r,
+ gdouble *g,
+ gdouble *b)
+{
+ gdouble min;
+ gdouble max;
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble h = 0;
+ gdouble l;
+ gdouble s;
+ gdouble delta;
+
+ red = *r;
+ green = *g;
+ blue = *b;
+
+ if (red > green)
+ {
+ if (red > blue)
+ max = red;
+ else
+ max = blue;
+
+ if (green < blue)
+ min = green;
+ else
+ min = blue;
+ }
+ else
+ {
+ if (green > blue)
+ max = green;
+ else
+ max = blue;
+
+ if (red < blue)
+ min = red;
+ else
+ min = blue;
+ }
+ l = (max+min)/2;
+ if (fabs (max-min) < 0.0001)
+ {
+ h = 0;
+ s = 0;
+ }
+ else
+ {
+ if (l <= 0.5)
+ s = (max-min)/(max+min);
+ else
+ s = (max-min)/(2-max-min);
+
+ delta = (max -min) != 0 ? (max -min) : 1;
+
+ if(delta == 0)
+ delta = 1;
+ if (red == max)
+ h = (green-blue)/delta;
+ else if (green == max)
+ h = 2+(blue-red)/delta;
+ else if (blue == max)
+ h = 4+(red-green)/delta;
+
+ h *= 60;
+ if (h < 0.0)
+ h += 360;
+ }
+
+ *r = h;
+ *g = l;
+ *b = s;
+}
+
+static void
+_color_hls_to_rgb (gdouble *h,
+ gdouble *l,
+ gdouble *s)
+{
+ gdouble hue;
+ gdouble lightness;
+ gdouble saturation;
+ gdouble m1, m2;
+ gdouble r, g, b;
+
+ lightness = *l;
+ saturation = *s;
+
+ if (lightness <= 0.5)
+ m2 = lightness*(1+saturation);
+ else
+ m2 = lightness+saturation-lightness*saturation;
+
+ m1 = 2*lightness-m2;
+
+ if (saturation == 0)
+ {
+ *h = lightness;
+ *l = lightness;
+ *s = lightness;
+ }
+ else
+ {
+ hue = *h+120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ r = m1+(m2-m1)*hue/60;
+ else if (hue < 180)
+ r = m2;
+ else if (hue < 240)
+ r = m1+(m2-m1)*(240-hue)/60;
+ else
+ r = m1;
+
+ hue = *h;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ g = m1+(m2-m1)*hue/60;
+ else if (hue < 180)
+ g = m2;
+ else if (hue < 240)
+ g = m1+(m2-m1)*(240-hue)/60;
+ else
+ g = m1;
+
+ hue = *h-120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ b = m1+(m2-m1)*hue/60;
+ else if (hue < 180)
+ b = m2;
+ else if (hue < 240)
+ b = m1+(m2-m1)*(240-hue)/60;
+ else
+ b = m1;
+
+ *h = r;
+ *l = g;
+ *s = b;
+ }
+}
+
+void
+_color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b)
+{
+ double red;
+ double green;
+ double blue;
+
+ red = a->r;
+ green = a->g;
+ blue = a->b;
+
+ if (k == 1.0)
+ {
+ b->r = red;
+ b->g = green;
+ b->b = blue;
+ return;
+ }
+
+ _color_rgb_to_hls (&red, &green, &blue);
+
+ green *= k;
+ if (green > 1.0)
+ green = 1.0;
+ else if (green < 0.0)
+ green = 0.0;
+
+ blue *= k;
+ if (blue > 1.0)
+ blue = 1.0;
+ else if (blue < 0.0)
+ blue = 0.0;
+
+ _color_hls_to_rgb (&red, &green, &blue);
+
+ b->r = red;
+ b->g = green;
+ b->b = blue;
+}
+
+
+/*****************************************************************/
+
/* Suppress/consume keyevents */
static gboolean
user_widget_button_release_event (GtkWidget *menuitem,
@@ -291,6 +621,10 @@ user_widget_button_release_event (GtkWidget *menuitem,
return FALSE;
}
+
+/**
+ * TODO, be sensitive to UI updates
+ * */
static void
user_widget_property_update (DbusmenuMenuitem* item, gchar* property,
GVariant* value, gpointer userdata)
@@ -300,6 +634,8 @@ user_widget_property_update (DbusmenuMenuitem* item, gchar* property,
}
+
+
static void
user_widget_set_twin_item (UserWidget* self,
DbusmenuMenuitem* twin_item)
@@ -325,9 +661,48 @@ user_widget_set_twin_item (UserWidget* self,
gtk_widget_hide(priv->tick_icon);
}
- g_debug("Using user icon for '%s' from file: %s",
- dbusmenu_menuitem_property_get(twin_item, USER_ITEM_PROP_NAME), icon_name);
+ GdkPixbuf* pixbuf = NULL;
+ GError* error = NULL;
+ pixbuf = gdk_pixbuf_new_from_file_at_size(icon_name, 32, 32, NULL);
+
+ if (pixbuf == NULL || error != NULL) {
+ g_warning ("Could not load the user image (%s) for some reason",
+ icon_name);
+ if (pixbuf != NULL){
+ g_object_unref (pixbuf);
+ pixbuf = NULL;
+ }
+ if (error != NULL){
+ g_error_free (error);
+ error = NULL;
+ }
+
+ priv->using_personal_icon = FALSE;
+
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ USER_ITEM_ICON_DEFAULT,
+ 32,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ &error);
+ }
+ else{
+ priv->using_personal_icon = TRUE;
+ }
+ if (pixbuf == NULL || error != NULL) {
+ g_warning ("Could not load the user image");
+ if (error != NULL){
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+ else{
+ gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf);
+ }
+ if (pixbuf != NULL){
+ g_object_unref (pixbuf);
+ pixbuf = NULL;
+ }
}
/**