changeset 14935:ef80d4c30a90

[gaim-migrate @ 17707] Change the way tooltips are displayed. This fixes crashes when the tooltip for a contact grows too large. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Thu, 09 Nov 2006 00:20:18 +0000
parents 4504a21b1d8f
children 5025e146a876
files console/gntblist.c
diffstat 1 files changed, 48 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/console/gntblist.c	Wed Nov 08 10:22:00 2006 +0000
+++ b/console/gntblist.c	Thu Nov 09 00:20:18 2006 +0000
@@ -43,6 +43,7 @@
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
 #include "gnttree.h"
+#include "gntutils.h"
 #include "gntwindow.h"
 
 #include "gntblist.h"
@@ -163,13 +164,6 @@
 	ggblist->tnode = NULL;
 }
 
-static gboolean
-_draw_tooltip(gpointer data)
-{
-	draw_tooltip(data);
-	return FALSE;
-}
-
 static void
 node_remove(GaimBuddyList *list, GaimBlistNode *node)
 {
@@ -193,12 +187,7 @@
 			node_remove(list, node->parent);
 	}
 
-	/* When an account has signed off, it removes one buddy at a time.
-	 * Drawing the tooltip after removing each buddy is expensive. On
-	 * top of that, if the selected buddy belongs to the disconnected
-	 * account, then retreiving the tooltip for that causes crash. So
-	 * let's make sure we wait for all the buddies to be removed first.*/
-	g_timeout_add(0, _draw_tooltip, ggblist);
+	draw_tooltip(ggblist);
 }
 
 static void
@@ -1149,14 +1138,24 @@
 	}
 }
 
-static void
-draw_tooltip(GGBlist *ggblist)
+static GString*
+make_sure_text_fits(GString *string)
+{
+	int maxw = getmaxx(stdscr) - 3;
+	char *str = gnt_util_onscreen_fit_string(string->str, maxw);
+	string = g_string_assign(string, str);
+	g_free(str);
+	return string;
+}
+
+static gboolean
+draw_tooltip_real(GGBlist *ggblist)
 {
 	GaimBlistNode *node;
-	int x, y, top, width;
+	int x, y, top, width, w, h;
 	GString *str;
 	GntTree *tree;
-	GntWidget *widget, *box;
+	GntWidget *widget, *box, *tv;
 	char *title = NULL;
 	int lastseen = 0;
 
@@ -1165,7 +1164,7 @@
 
 	if (!gnt_widget_has_focus(ggblist->tree) || 
 			(ggblist->context && !GNT_WIDGET_IS_FLAG_SET(ggblist->context, GNT_WIDGET_INVISIBLE)))
-		return;
+		return FALSE;
 
 	if (ggblist->tooltip)
 	{
@@ -1176,7 +1175,7 @@
 
 	node = gnt_tree_get_selection_data(tree);
 	if (!node)
-		return;
+		return FALSE;
 
 	str = g_string_new("");
 
@@ -1192,6 +1191,7 @@
 			g_string_append_printf(str, _("Nickname: %s\n"), gaim_buddy_get_name(pr));
 		tooltip_for_buddy(pr, str);
 		for (node = node->child; node; node = node->next) {
+			GaimBuddy *buddy = (GaimBuddy*)node;
 			if (offline) {
 				int value = gaim_blist_node_get_int(node, "last_seen");
 				if (value > lastseen)
@@ -1199,11 +1199,13 @@
 			}
 			if (node == (GaimBlistNode*)pr)
 				continue;
-			if (!showoffline && !GAIM_BUDDY_IS_ONLINE((GaimBuddy*)node))
+			if (!gaim_account_is_connected(buddy->account))
+				continue;
+			if (!showoffline && !GAIM_BUDDY_IS_ONLINE(buddy))
 				continue;
 			str = g_string_append(str, "\n----------\n");
-			g_string_append_printf(str, _("Nickname: %s\n"), gaim_buddy_get_name((GaimBuddy*)node));
-			tooltip_for_buddy((GaimBuddy*)node, str);
+			g_string_append_printf(str, _("Nickname: %s\n"), gaim_buddy_get_name(buddy));
+			tooltip_for_buddy(buddy, str);
 		}
 	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
 		GaimBuddy *buddy = (GaimBuddy *)node;
@@ -1230,7 +1232,7 @@
 		title = g_strdup(gaim_chat_get_name(chat));
 	} else {
 		g_string_free(str, TRUE);
-		return;
+		return FALSE;
 	}
 
 	if (lastseen > 0) {
@@ -1251,19 +1253,41 @@
 	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW);
 	gnt_box_set_title(GNT_BOX(box), title);
 
-	gnt_box_add_widget(GNT_BOX(box), gnt_label_new(str->str));
+	str = make_sure_text_fits(str);
+	gnt_util_get_text_bound(str->str, &w, &h);
+	h = MAX(2, h);
+	tv = gnt_text_view_new();
+	gnt_widget_set_size(tv, w + 1, h);
+	gnt_box_add_widget(GNT_BOX(box), tv);
 
 	gnt_widget_set_position(box, x, y);
 	GNT_WIDGET_UNSET_FLAGS(box, GNT_WIDGET_CAN_TAKE_FOCUS);
 	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
 	gnt_widget_draw(box);
 
+	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(tv), str->str, GNT_TEXT_FLAG_NORMAL);
+	gnt_text_view_scroll(GNT_TEXT_VIEW(tv), 0);
+
 	g_free(title);
 	g_string_free(str, TRUE);
 	ggblist->tooltip = box;
 	ggblist->tnode = node;
 
 	gnt_widget_set_name(ggblist->tooltip, "tooltip");
+	return FALSE;
+}
+
+static void
+draw_tooltip(GGBlist *ggblist)
+{
+	/* When an account has signed off, it removes one buddy at a time.
+	 * Drawing the tooltip after removing each buddy is expensive. On
+	 * top of that, if the selected buddy belongs to the disconnected
+	 * account, then retreiving the tooltip for that causes crash. So
+	 * let's make sure we wait for all the buddies to be removed first.*/
+	int id = g_timeout_add(0, draw_tooltip_real, ggblist);
+	g_object_set_data_full(G_OBJECT(ggblist->window), "draw_tooltip_calback",
+				GINT_TO_POINTER(id), (GDestroyNotify)g_source_remove);
 }
 
 static void