changeset 15238:ea246204cf36

[gaim-migrate @ 18028] Draw a small "close-button" in the buddylist-headline when the cursor is moved over it. I was drawing the close button all the time first, but showing it only on hover seemed like a better idea. Clicking the close-button will close the headline box without triggering the callback. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 20 Dec 2006 09:28:29 +0000
parents 658f815e2b58
children 30932055bb7c
files gtk/gtkblist.c gtk/gtkblist.h
diffstat 2 files changed, 76 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/gtkblist.c	Wed Dec 20 05:50:49 2006 +0000
+++ b/gtk/gtkblist.c	Wed Dec 20 09:28:29 2006 +0000
@@ -61,6 +61,8 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
+#define HEADLINE_CLOSE_SIZE 12
+
 typedef struct
 {
 	GaimAccount *account;
@@ -268,6 +270,8 @@
 	gaim_prefs_set_int("/gaim/gtk/blist/width",  event->width);
 	gaim_prefs_set_int("/gaim/gtk/blist/height", event->height);
 
+	gtk_widget_set_size_request(gtkblist->headline_label,
+				    gaim_prefs_get_int("/gaim/gtk/blist/width")-25,-1);
 	/* continue to handle event normally */
 	return FALSE;
 }
@@ -3673,16 +3677,63 @@
 }
 
 static gboolean
+headline_hover_close(int x, int y)
+{
+	GtkWidget *w = gtkblist->headline_hbox;
+	if (x <= w->allocation.width && x >= w->allocation.width - HEADLINE_CLOSE_SIZE &&
+			y >= 0 && y <= HEADLINE_CLOSE_SIZE)
+		return TRUE;
+	return FALSE;
+}
+
+static gboolean
 headline_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, GaimGtkBuddyList *gtkblist)
 {
 	gdk_window_set_cursor(widget->window, gtkblist->hand_cursor);
+
+	if (gtkblist->headline_close) {
+#if GTK_CHECK_VERSION(2,2,0)
+		gdk_draw_pixbuf(widget->window, NULL, gtkblist->headline_close,
+#else
+		gdk_pixbuf_render_to_drawable(gtkblist->headline_close,
+				GDK_DRAWABLE(widget->window), NULL,
+#endif
+					0, 0,
+					widget->allocation.width - 2 - HEADLINE_CLOSE_SIZE, 2,
+					HEADLINE_CLOSE_SIZE, HEADLINE_CLOSE_SIZE,
+					GDK_RGB_DITHER_NONE, 0, 0);
+		gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT,
+				NULL, widget, NULL,
+				widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1,
+				HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2);
+	}
+
 	return FALSE;
 }
 
+#if 0
+static gboolean
+headline_box_motion_cb(GtkWidget *widget, GdkEventMotion *event, GaimGtkBuddyList *gtkblist)
+{
+	gaim_debug_fatal("motion", "%d %d\n", (int)event->x, (int)event->y);
+	if (headline_hover_close((int)event->x, (int)event->y))
+		gtk_paint_focus(widget->style, widget->window, GTK_STATE_PRELIGHT,
+				NULL, widget, NULL,
+				widget->allocation.width - HEADLINE_CLOSE_SIZE - 3, 1,
+				HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2);
+	return FALSE;
+}
+#endif
+
 static gboolean
 headline_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, GaimGtkBuddyList *gtkblist)
 {
 	gdk_window_set_cursor(widget->window, gtkblist->arrow_cursor);
+	if (gtkblist->headline_close) {
+		GdkRectangle rect = {widget->allocation.width - 3 - HEADLINE_CLOSE_SIZE, 1,
+				HEADLINE_CLOSE_SIZE + 2, HEADLINE_CLOSE_SIZE + 2};
+		gdk_window_invalidate_rect(widget->window, &rect, TRUE);
+	}
 	return FALSE;
 }
 
@@ -3697,7 +3748,7 @@
 headline_box_press_cb(GtkWidget *widget, GdkEventButton *event, GaimGtkBuddyList *gtkblist)
 {
 	gtk_widget_hide(gtkblist->headline_hbox);
-	if (gtkblist->headline_callback)
+	if (gtkblist->headline_callback && !headline_hover_close((int)event->x, (int)event->y))
 		g_idle_add((GSourceFunc)headline_click_callback, gtkblist->headline_data);
 	return TRUE;
 }
@@ -3824,9 +3875,9 @@
 static gboolean
 paint_headline_hbox  (GtkWidget      *widget,
 		      GdkEventExpose *event,
-		      gpointer        user_data)
-{
-  gtk_paint_flat_box (widget->style,
+		      gpointer user_data)
+{
+	gtk_paint_flat_box (widget->style,
 		      widget->window,
 		      GTK_STATE_NORMAL,
 		      GTK_SHADOW_OUT,
@@ -3837,8 +3888,7 @@
 		      widget->allocation.y + 1,
 		      widget->allocation.width - 2,
 		      widget->allocation.height - 2);
-
-  return FALSE;
+	return FALSE;
 }
 
 static void
@@ -4044,11 +4094,27 @@
 			  NULL);
 	gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips");
 
+	gtkblist->headline_close = gtk_widget_render_icon(ebox, GTK_STOCK_CLOSE, -1, NULL);
+	if (gtkblist->headline_close) {
+		GdkPixbuf *scale = gdk_pixbuf_scale_simple(gtkblist->headline_close,
+				HEADLINE_CLOSE_SIZE, HEADLINE_CLOSE_SIZE, GDK_INTERP_BILINEAR);
+		gdk_pixbuf_unref(gtkblist->headline_close);
+		gtkblist->headline_close = scale;
+	}
+
 	gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2);
 	gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+
 	g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(headline_box_enter_cb), gtkblist);
 	g_signal_connect(G_OBJECT(ebox), "leave-notify-event", G_CALLBACK(headline_box_leave_cb), gtkblist);
 	g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(headline_box_press_cb), gtkblist);
+#if 0
+	/* I couldn't get this to work. The idea was to draw the focus-border only
+	 * when hovering over the close image. So for now, the focus-border is
+	 * always there. -- sad */
+	gtk_widget_set_events(ebox, gtk_widget_get_events(ebox) | GDK_POINTER_MOTION_HINT_MASK);
+	g_signal_connect(G_OBJECT(ebox), "motion-notify-event", G_CALLBACK(headline_box_motion_cb), gtkblist);
+#endif
 
 	/****************************** GtkTreeView **********************************/
 	sw = gtk_scrolled_window_new(NULL,NULL);
@@ -4833,6 +4899,9 @@
 
 	gaim_signals_disconnect_by_handle(gtkblist);
 
+	if (gtkblist->headline_close)
+		gdk_pixbuf_unref(gtkblist->headline_close);
+
 	gtk_widget_destroy(gtkblist->window);
 
 	gaim_gtk_blist_tooltip_destroy();
--- a/gtk/gtkblist.h	Wed Dec 20 05:50:49 2006 +0000
+++ b/gtk/gtkblist.h	Wed Dec 20 09:28:29 2006 +0000
@@ -103,6 +103,7 @@
 	GtkWidget *headline_hbox;       /**< Hbox for headline notification */
 	GtkWidget *headline_label;	/**< Label for headline notifications */
 	GtkWidget *headline_image;      /**< Image for headline notifications */
+	GdkPixbuf *headline_close;      /**< Close image for closing the headline without triggering the callback */
 	GCallback headline_callback;    /**< Callback for headline notifications */
 	gpointer headline_data;         /**< User data for headline notifications */
 	gboolean changing_style;        /**< True when changing GTK+ theme style */