changeset 18671:30b6f8bc47cf

Tooltips in infopanes
author Sean Egan <seanegan@gmail.com>
date Sat, 28 Jul 2007 05:08:08 +0000
parents 70c758256110
children 7c8321023ae5
files ChangeLog.API pidgin/gtkblist.c pidgin/gtkblist.h pidgin/gtkconv.c
diffstat 4 files changed, 99 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sat Jul 28 04:27:18 2007 +0000
+++ b/ChangeLog.API	Sat Jul 28 05:08:08 2007 +0000
@@ -74,6 +74,8 @@
 		* pidgin_menu_position_func_helper
 		* pidgin_blist_get_name_markup, returns the buddy list markup
 		  text for a given buddy.
+		* pidgin_blist_draw_tooltip and pidgin_blist_tooltip_destroy
+		  for creating blist tooltips from outside of buddy list code
 		* pidgin_themes_remove_smiley_theme
 
 		Changed:
--- a/pidgin/gtkblist.c	Sat Jul 28 04:27:18 2007 +0000
+++ b/pidgin/gtkblist.c	Sat Jul 28 05:08:08 2007 +0000
@@ -136,8 +136,6 @@
 static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node);
 static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded);
 
-static void pidgin_blist_tooltip_destroy(void);
-
 struct _pidgin_blist_node {
 	GtkTreeRowReference *row;
 	gboolean contact_expanded;
@@ -1150,7 +1148,8 @@
 	pidgin_new_item_from_stock(menu, _("Add Buddy _Pounce"), NULL,
 			G_CALLBACK(gtk_blist_menu_bp_cb), buddy, 0, 0, NULL);
 
-	if(((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) {
+	if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && 
+	      !sub && !contact_expanded) {
 		pidgin_new_item_from_stock(menu, _("View _Log"), NULL,
 				G_CALLBACK(gtk_blist_menu_showlog_cb),
 				contact, 0, 0, NULL);
@@ -1164,7 +1163,8 @@
 										  (PurpleBlistNode *)buddy);
 	pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
 
-	if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) {
+	if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && 
+              !sub && !contact_expanded) {
 		pidgin_separator(menu);
 		pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
 		pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
@@ -2496,7 +2496,7 @@
 }
 
 
-static void pidgin_blist_tooltip_destroy()
+void pidgin_blist_tooltip_destroy()
 {
 	while(gtkblist->tooltipdata) {
 		struct tooltip_data *td = gtkblist->tooltipdata->data;
@@ -2584,6 +2584,22 @@
 	GtkTreeIter iter;
 	PurpleBlistNode *node;
 	GValue val;
+
+	if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL))
+		return FALSE;
+	gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
+	val.g_type = 0;
+	gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val);
+	node = g_value_get_pointer(&val);
+
+	pidgin_blist_draw_tooltip(node, gtkblist->window);
+
+	gtk_tree_path_free(path);
+	return FALSE;
+}
+
+void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget)
+{
 	int scr_w, scr_h, w, h, x, y;
 #if GTK_CHECK_VERSION(2,2,0)
 	int mon_num;
@@ -2592,6 +2608,9 @@
 	gboolean tooltip_top = FALSE;
 	struct _pidgin_blist_node *gtknode;
 	GdkRectangle mon_size;
+	
+	if (node == NULL)
+		return;
 
 	/*
 	 * Attempt to free the previous tooltip.  I have a feeling
@@ -2599,14 +2618,6 @@
 	 */
 	pidgin_blist_tooltip_destroy();
 
-	if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL))
-		return FALSE;
-	gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
-	val.g_type = 0;
-	gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val);
-	node = g_value_get_pointer(&val);
-
-	gtk_tree_path_free(path);
 
 	gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP);
 
@@ -2644,13 +2655,13 @@
 	} else {
 		gtk_widget_destroy(gtkblist->tipwindow);
 		gtkblist->tipwindow = NULL;
-		return FALSE;
+		return;
 	}
 
 	if (gtkblist->tooltipdata == NULL) {
 		gtk_widget_destroy(gtkblist->tipwindow);
 		gtkblist->tipwindow = NULL;
-		return FALSE;
+		return;
 	}
 
 	gtknode = node->ui_data;
@@ -2686,9 +2697,6 @@
 	  h = mon_size.height - 10;
 #endif
 
-	if (GTK_WIDGET_NO_WINDOW(gtkblist->window))
-		y+=gtkblist->window->allocation.y;
-
 	x -= ((w >> 1) + 4);
 
 	if ((y + h + 4) > scr_h || tooltip_top)
@@ -2714,7 +2722,7 @@
 	gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y);
 	gtk_widget_show(gtkblist->tipwindow);
 
-	return FALSE;
+	return;
 }
 
 static gboolean pidgin_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context,
--- a/pidgin/gtkblist.h	Sat Jul 28 04:27:18 2007 +0000
+++ b/pidgin/gtkblist.h	Sat Jul 28 05:08:08 2007 +0000
@@ -370,4 +370,21 @@
  */
 gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected, gboolean aliased);
 
+/**
+ * Creates the Buddy List tooltip at the current pointer location for the given buddy list node.
+ *
+ * This tooltip will be destroyed the next time this function is called, or when XXXX
+ * is called
+ *
+ * @param buddy The buddy to show a tooltip for
+ * @param widget The widget to draw the tooltip on
+ */
+void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget);
+
+/**
+ * Destroys the current (if any) Buddy List tooltip
+ */
+void pidgin_blist_tooltip_destroy(void);
+
+
 #endif /* _PIDGINBLIST_H_ */
--- a/pidgin/gtkconv.c	Sat Jul 28 04:27:18 2007 +0000
+++ b/pidgin/gtkconv.c	Sat Jul 28 05:08:08 2007 +0000
@@ -4408,6 +4408,50 @@
 	gtk_container_add(GTK_CONTAINER(sw), list);
 }
 
+static int tooltip_timeout = 0;
+
+static gboolean
+pidgin_conv_tooltip_timeout(PidginConversation *gtkconv)
+{
+	PurpleBlistNode *node = NULL;
+	PurpleConversation *conv = gtkconv->active_conv;
+ 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
+                node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name));
+	} else {
+                node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name));
+	}
+
+	if (node) 
+		pidgin_blist_draw_tooltip(node, gtkconv->infopane);
+	return FALSE;
+}
+
+static void 
+pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv)
+{
+	pidgin_blist_tooltip_destroy();
+	if (tooltip_timeout) {
+		g_source_remove(tooltip_timeout);
+		tooltip_timeout = 0;
+	}
+}
+
+static gboolean 
+pidgin_conv_motion_cb (GtkWidget *infopane, GdkEventMotion *event, PidginConversation *gtkconv)
+{
+	int delay = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/tooltip_delay");
+	
+	pidgin_blist_tooltip_destroy();
+	if (delay == 0)
+		return FALSE;
+
+	if (tooltip_timeout != 0) 
+		g_source_remove(tooltip_timeout);
+
+	tooltip_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_conv_tooltip_timeout, gtkconv);
+	return FALSE;
+}
+
 static GtkWidget *
 setup_common_pane(PidginConversation *gtkconv)
 {
@@ -4437,10 +4481,15 @@
 	gtk_container_add(GTK_CONTAINER(event_box), gtkconv->infopane_hbox);
 	gtk_widget_show(gtkconv->infopane_hbox);
 	gtk_widget_add_events(event_box,
-	                      GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
+	                      GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
 	g_signal_connect(G_OBJECT(event_box), "button_press_event",
 	                 G_CALLBACK(infopane_press_cb), gtkconv);
 
+        g_signal_connect(G_OBJECT(event_box), "motion-notify-event", 
+			 G_CALLBACK(pidgin_conv_motion_cb), gtkconv);
+        g_signal_connect(G_OBJECT(event_box), "leave-notify-event", 
+			 G_CALLBACK(pidgin_conv_leave_cb), gtkconv);
+
 
 	gtkconv->infopane = gtk_cell_view_new();
 	gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF);
@@ -7660,8 +7709,6 @@
 static gboolean
 infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv)
 {
-	int nb_x, nb_y;
-
 	if (e->type != GDK_BUTTON_PRESS)
 		return FALSE;
 
@@ -7692,39 +7739,10 @@
 		gtk_widget_show_all(menu);
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time);
 		return TRUE;
-	} else if (e->button != 1) {
-		return FALSE;
-	}
-
-	if (gtkconv->win->in_drag) {
-		purple_debug(PURPLE_DEBUG_WARNING, "gtkconv",
-				"Already in the middle of a window drag at tab_press_cb\n");
-		return TRUE;
-	}
-
-	gtkconv->win->in_predrag = TRUE;
-	gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont);
-
-	gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y);
-
-	gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x      + nb_x;
-	gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y      + nb_y;
-	gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width  + gtkconv->win->drag_min_x;
-	gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y;
-
-	/* Connect the new motion signals. */
-	gtkconv->win->drag_motion_signal =
-		g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event",
-				G_CALLBACK(notebook_motion_cb), gtkconv->win);
-
-	gtkconv->win->drag_leave_signal =
-		g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event",
-				G_CALLBACK(notebook_leave_cb), gtkconv->win);
-
+	}
 	return FALSE;
-
-}
-
+}
+ 
 static gboolean
 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win)
 {