diff src/conversation.c @ 2191:657dbe515608

[gaim-migrate @ 2201] genericize buddy icon stuff committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 29 Aug 2001 23:41:43 +0000
parents edf8c5a70e5b
children d615f7e2d8c4
line wrap: on
line diff
--- a/src/conversation.c	Wed Aug 29 23:38:38 2001 +0000
+++ b/src/conversation.c	Wed Aug 29 23:41:43 2001 +0000
@@ -75,6 +75,9 @@
 void check_everything(GtkWidget *entry);
 gboolean keypress_callback(GtkWidget *entry, GdkEventKey * event, struct conversation *c);
 
+static void update_icon(struct conversation *);
+static void remove_icon(struct conversation *);
+
 /*------------------------------------------------------------------------*/
 /*  Helpers                                                               */
 /*------------------------------------------------------------------------*/
@@ -156,6 +159,7 @@
 	show_conv(c);
 	if (c->gc && c->gc->prpl && c->gc->prpl->insert_convo)
 		(*c->gc->prpl->insert_convo)(c->gc, c);
+	update_icon(c);
 	plugin_event(event_new_conversation, name, 0, 0, 0);
 	return c;
 }
@@ -411,6 +415,7 @@
 	if (!c->is_chat) {
 		if (c->gc && c->gc->prpl && c->gc->prpl->remove_convo)
 			(*c->gc->prpl->remove_convo)(c->gc, c);
+		remove_icon(c);
 		if (display_options & OPT_DISP_ONE_WINDOW) {
 			if (g_list_length(conversations) > 1) {
 				gtk_notebook_remove_page(GTK_NOTEBOOK(convo_notebook),
@@ -1785,6 +1790,7 @@
 
 	if (cnv->gc && cnv->gc->prpl && cnv->gc->prpl->insert_convo)
 		(*cnv->gc->prpl->insert_convo)(cnv->gc, cnv);
+	update_icon(cnv);
 }
 
 void update_convo_add_button(struct conversation *c)
@@ -1892,6 +1898,7 @@
 
 		if (C->gc && C->gc->prpl && C->gc->prpl->remove_convo)
 			(*C->gc->prpl->remove_convo)(C->gc, C);
+		remove_icon(C);
 	}
 }
 
@@ -1912,6 +1919,7 @@
 
 	if (c->gc && c->gc->prpl && c->gc->prpl->insert_convo)
 		(*c->gc->prpl->insert_convo)(c->gc, c);
+	update_icon(c);
 }
 
 void update_buttons_by_protocol(struct conversation *c)
@@ -2336,6 +2344,7 @@
 			win = c->window;
 			if (c->gc && c->gc->prpl->remove_convo)
 				(*c->gc->prpl->remove_convo)(c->gc, c);
+			remove_icon(c);
 			show_conv(c);
 			gtk_widget_destroy(c->text);
 			gtk_widget_reparent(imhtml, c->sw);
@@ -2343,6 +2352,7 @@
 			gtk_widget_destroy(win);
 			if (c->gc && c->gc->prpl->insert_convo)
 				(*c->gc->prpl->insert_convo)(c->gc, c);
+			update_icon(c);
 
 			x = x->next;
 		}
@@ -2357,12 +2367,14 @@
 			imhtml = c->text;
 			if (c->gc && c->gc->prpl->remove_convo)
 				(*c->gc->prpl->remove_convo)(c->gc, c);
+			remove_icon(c);
 			show_conv(c);
 			gtk_widget_destroy(c->text);
 			gtk_widget_reparent(imhtml, c->sw);
 			c->text = imhtml;
 			if (c->gc && c->gc->prpl->insert_convo)
 				(*c->gc->prpl->insert_convo)(c->gc, c);
+			update_icon(c);
 
 			x = x->next;
 		}
@@ -2461,3 +2473,181 @@
 		sprintf(b->fontface, "%s", fontface);
 	}
 }
+
+#if USE_PIXBUF
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixbuf-loader.h>
+#define SCALE 48
+
+static gboolean redraw_icon(gpointer data)
+{
+	struct conversation *c = data;
+
+	GList *frames;
+	GdkPixbufFrame *frame;
+	GdkPixbuf *buf;
+	GdkPixbuf *scale;
+	GdkPixmap *src;
+	GdkPixmap *pm;
+	GdkBitmap *bm;
+	GdkGC *gc;
+	gint delay;
+
+	if (!g_list_find(conversations, c)) {
+		debug_printf("I think this is a bug.\n");
+		return FALSE;
+	}
+
+	frames = gdk_pixbuf_animation_get_frames(c->anim);
+	frame = g_list_nth_data(frames, c->frame);
+	switch (gdk_pixbuf_frame_get_action(frame)) {
+	case GDK_PIXBUF_FRAME_RETAIN:
+		buf = gdk_pixbuf_frame_get_pixbuf(frame);
+		scale = gdk_pixbuf_scale_simple(buf,
+				MAX(gdk_pixbuf_get_width(buf) * SCALE /
+					gdk_pixbuf_animation_get_width(c->anim), 1),
+				MAX(gdk_pixbuf_get_height(buf) * SCALE /
+					gdk_pixbuf_animation_get_height(c->anim), 1),
+				GDK_INTERP_NEAREST);
+		gdk_pixbuf_render_pixmap_and_mask(scale, &src, NULL, 0);
+		gdk_pixbuf_unref(scale);
+		gtk_pixmap_get(GTK_PIXMAP(c->icon), &pm, &bm);
+		gc = gdk_gc_new(pm);
+		gdk_draw_pixmap(pm, gc, src, 0, 0,
+				MAX(gdk_pixbuf_frame_get_x_offset(frame) * SCALE /
+					gdk_pixbuf_animation_get_width(c->anim), 1),
+				MAX(gdk_pixbuf_frame_get_y_offset(frame) * SCALE /
+					gdk_pixbuf_animation_get_height(c->anim), 1),
+				-1, -1);
+		gdk_pixmap_unref(src);
+		gtk_widget_queue_draw(c->icon);
+		gdk_gc_unref(gc);
+		break;
+	case GDK_PIXBUF_FRAME_DISPOSE:
+		buf = gdk_pixbuf_frame_get_pixbuf(frame);
+		scale = gdk_pixbuf_scale_simple(buf,
+				MAX(gdk_pixbuf_get_width(buf) * SCALE /
+					gdk_pixbuf_animation_get_width(c->anim), 1),
+				MAX(gdk_pixbuf_get_height(buf) * SCALE /
+					gdk_pixbuf_animation_get_height(c->anim), 1),
+				GDK_INTERP_NEAREST);
+		gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
+		gdk_pixbuf_unref(scale);
+		gtk_pixmap_set(GTK_PIXMAP(c->icon), pm, bm);
+		gdk_pixmap_unref(pm);
+		if (bm)
+			gdk_bitmap_unref(bm);
+		break;
+	case GDK_PIXBUF_FRAME_REVERT:
+		frame = frames->data;
+		buf = gdk_pixbuf_frame_get_pixbuf(frame);
+		scale = gdk_pixbuf_scale_simple(buf,
+				MAX(gdk_pixbuf_get_width(buf) * SCALE /
+					gdk_pixbuf_animation_get_width(c->anim), 1),
+				MAX(gdk_pixbuf_get_height(buf) * SCALE /
+					gdk_pixbuf_animation_get_height(c->anim), 1),
+				GDK_INTERP_NEAREST);
+		gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
+		gdk_pixbuf_unref(scale);
+		gtk_pixmap_set(GTK_PIXMAP(c->icon), pm, bm);
+		gdk_pixmap_unref(pm);
+		if (bm)
+			gdk_bitmap_unref(bm);
+		break;
+	}
+
+	c->frame = (c->frame + 1) % g_list_length(frames);
+	delay = MAX(gdk_pixbuf_frame_get_delay_time(frame), 13);
+	c->icon_timer = gtk_timeout_add(delay * 10, redraw_icon, c);
+
+	return FALSE;
+}
+#endif
+
+void remove_icon(struct conversation *c)
+{
+#if USE_PIXBUF
+	if (c->icon)
+		gtk_container_remove(GTK_CONTAINER(c->bbox), c->icon);
+	c->icon = NULL;
+	if (c->anim)
+		gdk_pixbuf_animation_unref(c->anim);
+	c->anim = NULL;
+	if (c->unanim)
+		gdk_pixbuf_unref(c->unanim);
+	c->unanim = NULL;
+	if (c->icon_timer)
+		gtk_timeout_remove(c->icon_timer);
+	c->icon_timer = 0;
+	c->frame = 0;
+#endif
+}
+
+void update_icon(struct conversation *c)
+{
+#if USE_PIXBUF
+	void *data;
+	int len;
+
+	GdkPixbufLoader *load;
+	GdkPixbuf *scale;
+	GdkPixmap *pm;
+	GdkBitmap *bm;
+
+	if (!c)
+		return;
+
+	if (!c->gc)
+		return;
+	data = get_icon_data(c->gc, normalize(c->name), &len);
+	if (!data)
+		return;
+
+	load = gdk_pixbuf_loader_new();
+	gdk_pixbuf_loader_write(load, data, len);
+	c->anim = gdk_pixbuf_loader_get_animation(load);
+
+	if (c->anim) {
+		GList *frames = gdk_pixbuf_animation_get_frames(c->anim);
+		GdkPixbuf *buf = gdk_pixbuf_frame_get_pixbuf(frames->data);
+		scale = gdk_pixbuf_scale_simple(buf,
+				MAX(gdk_pixbuf_get_width(buf) * SCALE /
+					gdk_pixbuf_animation_get_width(c->anim), 1),
+				MAX(gdk_pixbuf_get_height(buf) * SCALE /
+					gdk_pixbuf_animation_get_height(c->anim), 1),
+				GDK_INTERP_NEAREST);
+
+		if (gdk_pixbuf_animation_get_num_frames(c->anim) > 1) {
+			int delay = MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13);
+			c->frame = 1;
+			c->icon_timer = gtk_timeout_add(delay * 10, redraw_icon, c);
+		}
+	} else {
+		c->unanim = gdk_pixbuf_loader_get_pixbuf(load);
+		if (!c->unanim) {
+			gdk_pixbuf_loader_close(load);
+			return;
+		}
+		scale = gdk_pixbuf_scale_simple(c->unanim, SCALE, SCALE, GDK_INTERP_NEAREST);
+	}
+
+	gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 0);
+	gdk_pixbuf_unref(scale);
+
+	c->icon = gtk_pixmap_new(pm, bm);
+	gtk_box_pack_start(GTK_BOX(c->bbox), c->icon, FALSE, FALSE, 5);
+	gtk_widget_show(c->icon);
+	gdk_pixmap_unref(pm);
+	if (bm)
+		gdk_bitmap_unref(bm);
+
+	gdk_pixbuf_loader_close(load);
+#endif
+}
+
+void got_new_icon(struct gaim_connection *gc, char *who)
+{
+	struct conversation *c = find_conversation(who);
+	if (c->gc == gc)
+		update_icon(c);
+}