diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2007-10-09 00:44:44 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@src.gnome.org> | 2007-10-09 00:44:44 +0800 |
commit | 0d4e81432f5ace47ac86991aa239e4a55686de00 (patch) | |
tree | 22cc64055c78370d4a973af8e85a36740f60f930 /libempathy-gtk/empathy-avatar-image.c | |
parent | 311dbc21826654538e098a8d838153d5b075f6c7 (diff) | |
download | gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.gz gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.bz2 gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.lz gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.xz gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.tar.zst gsoc2013-empathy-0d4e81432f5ace47ac86991aa239e4a55686de00.zip |
Implement EmpathyAvatarChooser and EmpathyAvatarImage and make use of them
2007-10-08 Xavier Claessens <xclaesse@gmail.com>
* libempathy-gtk/empathy-ui-utils.c:
* libempathy-gtk/empathy-ui-utils.h:
* libempathy-gtk/empathy-contact-widget.c:
* libempathy-gtk/empathy-contact-widget.h:
* libempathy-gtk/empathy-avatar-chooser.c:
* libempathy-gtk/empathy-avatar-chooser.h:
* libempathy-gtk/empathy-avatar-image.c:
* libempathy-gtk/empathy-avatar-image.h:
* libempathy-gtk/Makefile.am:
* src/empathy.c: Implement EmpathyAvatarChooser and EmpathyAvatarImage
and make use of them in contact information windows. That means we can
now enlarge avatars when clicking on it and we can set our own avatar if
we edit our own contact.
svn path=/trunk/; revision=363
Diffstat (limited to 'libempathy-gtk/empathy-avatar-image.c')
-rw-r--r-- | libempathy-gtk/empathy-avatar-image.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/libempathy-gtk/empathy-avatar-image.c b/libempathy-gtk/empathy-avatar-image.c new file mode 100644 index 000000000..cc4ecbf45 --- /dev/null +++ b/libempathy-gtk/empathy-avatar-image.c @@ -0,0 +1,306 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2006-2007 Imendio AB + * Copyright (C) 2007 Collabora Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Xavier Claessens <xclaesse@gmail.com> + */ + +#include "config.h" + +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include <gdk/gdkx.h> + +#include <libempathy/empathy-debug.h> + +#include "empathy-avatar-image.h" +#include "empathy-ui-utils.h" + +#define DEBUG_DOMAIN "AvatarImage" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_AVATAR_IMAGE, EmpathyAvatarImagePriv)) + +#define MAX_SMALL 48 +#define MAX_LARGE 400 + +typedef struct { + GtkWidget *image; + GtkWidget *popup; + GdkPixbuf *pixbuf; +} EmpathyAvatarImagePriv; + +static void avatar_image_finalize (GObject *object); +static void avatar_image_add_filter (EmpathyAvatarImage *avatar_image); +static void avatar_image_remove_filter (EmpathyAvatarImage *avatar_image); +static gboolean avatar_image_button_press_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean avatar_image_button_release_event (GtkWidget *widget, + GdkEventButton *event); + +G_DEFINE_TYPE (EmpathyAvatarImage, empathy_avatar_image, GTK_TYPE_EVENT_BOX); + +static void +empathy_avatar_image_class_init (EmpathyAvatarImageClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = G_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = avatar_image_finalize; + + widget_class->button_press_event = avatar_image_button_press_event; + widget_class->button_release_event = avatar_image_button_release_event; + + g_type_class_add_private (object_class, sizeof (EmpathyAvatarImagePriv)); +} + +static void +empathy_avatar_image_init (EmpathyAvatarImage *avatar_image) +{ + EmpathyAvatarImagePriv *priv; + + priv = GET_PRIV (avatar_image); + + priv->image = gtk_image_new (); + gtk_container_add (GTK_CONTAINER (avatar_image), priv->image); + empathy_avatar_image_set (avatar_image, NULL); + gtk_widget_show (priv->image); + + avatar_image_add_filter (avatar_image); +} + +static void +avatar_image_finalize (GObject *object) +{ + EmpathyAvatarImagePriv *priv; + + priv = GET_PRIV (object); + + avatar_image_remove_filter (EMPATHY_AVATAR_IMAGE (object)); + + if (priv->popup) { + gtk_widget_destroy (priv->popup); + } + + if (priv->pixbuf) { + g_object_unref (priv->pixbuf); + } + + G_OBJECT_CLASS (empathy_avatar_image_parent_class)->finalize (object); +} + +static GdkFilterReturn +avatar_image_filter_func (GdkXEvent *gdkxevent, + GdkEvent *event, + gpointer data) +{ + XEvent *xevent = gdkxevent; + Atom atom; + EmpathyAvatarImagePriv *priv; + + priv = GET_PRIV (data); + + switch (xevent->type) { + case PropertyNotify: + atom = gdk_x11_get_xatom_by_name ("_NET_CURRENT_DESKTOP"); + if (xevent->xproperty.atom == atom) { + if (priv->popup) { + gtk_widget_destroy (priv->popup); + priv->popup = NULL; + } + } + break; + } + + return GDK_FILTER_CONTINUE; +} + +static void +avatar_image_add_filter (EmpathyAvatarImage *avatar_image) +{ + Window window; + GdkWindow *gdkwindow; + gint mask; + + mask = PropertyChangeMask; + + window = GDK_ROOT_WINDOW (); + gdkwindow = gdk_xid_table_lookup (window); + + gdk_error_trap_push (); + if (gdkwindow) { + XWindowAttributes attrs; + XGetWindowAttributes (gdk_display, window, &attrs); + mask |= attrs.your_event_mask; + } + + XSelectInput (gdk_display, window, mask); + + gdk_error_trap_pop (); + + gdk_window_add_filter (NULL, avatar_image_filter_func, avatar_image); +} + +static void +avatar_image_remove_filter (EmpathyAvatarImage *avatar_image) +{ + gdk_window_remove_filter (NULL, avatar_image_filter_func, avatar_image); +} + +static gboolean +avatar_image_button_press_event (GtkWidget *widget, GdkEventButton *event) +{ + EmpathyAvatarImagePriv *priv; + GtkWidget *popup; + GtkWidget *frame; + GtkWidget *image; + gint x, y; + gint popup_width, popup_height; + gint width, height; + GdkPixbuf *pixbuf; + + priv = GET_PRIV (widget); + + if (priv->popup) { + gtk_widget_destroy (priv->popup); + priv->popup = NULL; + } + + if (event->button != 1 || event->type != GDK_BUTTON_PRESS || !priv->pixbuf) { + return FALSE; + } + + popup_width = gdk_pixbuf_get_width (priv->pixbuf); + popup_height = gdk_pixbuf_get_height (priv->pixbuf); + + width = priv->image->allocation.width; + height = priv->image->allocation.height; + + /* Don't show a popup if the popup is smaller then the currently avatar + * image. + */ + if (popup_height <= height && popup_width <= width) { + return TRUE; + } + + pixbuf = empathy_pixbuf_scale_down_if_necessary (priv->pixbuf, MAX_LARGE); + popup_width = gdk_pixbuf_get_width (pixbuf); + popup_height = gdk_pixbuf_get_height (pixbuf); + + popup = gtk_window_new (GTK_WINDOW_POPUP); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); + + gtk_container_add (GTK_CONTAINER (popup), frame); + + image = gtk_image_new (); + gtk_container_add (GTK_CONTAINER (frame), image); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); + g_object_unref (pixbuf); + + gdk_window_get_origin (priv->image->window, &x, &y); + + x = x - (popup_width - width) / 2; + y = y - (popup_height - height) / 2; + + gtk_window_move (GTK_WINDOW (popup), x, y); + + priv->popup = popup; + + gtk_widget_show_all (popup); + + return TRUE; +} + +static gboolean +avatar_image_button_release_event (GtkWidget *widget, GdkEventButton *event) +{ + EmpathyAvatarImagePriv *priv; + + priv = GET_PRIV (widget); + + if (event->button != 1 || event->type != GDK_BUTTON_RELEASE) { + return FALSE; + } + + if (!priv->popup) { + return TRUE; + } + + gtk_widget_destroy (priv->popup); + priv->popup = NULL; + + return TRUE; +} + +GtkWidget * +empathy_avatar_image_new (void) +{ + EmpathyAvatarImage *avatar_image; + + avatar_image = g_object_new (EMPATHY_TYPE_AVATAR_IMAGE, NULL); + + return GTK_WIDGET (avatar_image); +} + +void +empathy_avatar_image_set (EmpathyAvatarImage *avatar_image, + EmpathyAvatar *avatar) +{ + EmpathyAvatarImagePriv *priv = GET_PRIV (avatar_image); + GdkPixbuf *scaled_pixbuf; + + g_return_if_fail (EMPATHY_IS_AVATAR_IMAGE (avatar_image)); + + if (priv->pixbuf) { + g_object_unref (priv->pixbuf); + priv->pixbuf = NULL; + } + + if (avatar) { + priv->pixbuf = empathy_pixbuf_from_data (avatar->data, avatar->len); + } + + if (!priv->pixbuf) { + gtk_image_set_from_icon_name (GTK_IMAGE (priv->image), + "stock_person", + GTK_ICON_SIZE_DIALOG); + return; + } + + scaled_pixbuf = empathy_pixbuf_scale_down_if_necessary (priv->pixbuf, MAX_SMALL); + gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), scaled_pixbuf); + + if (scaled_pixbuf != priv->pixbuf) { + gtk_widget_set_tooltip_text (GTK_WIDGET (avatar_image), + _("Click to enlarge")); + } else { + gtk_widget_set_tooltip_text (GTK_WIDGET (avatar_image), + NULL); + } + + g_object_unref (scaled_pixbuf); +} + |