[accounts-dialog: 2/2] Fancy tooltips
- From: Matthias Clasen <matthiasc src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [accounts-dialog: 2/2] Fancy tooltips
- Date: Tue, 2 Feb 2010 15:46:10 +0000 (UTC)
commit 806970d0b3d8ea05a1e2436eb53e4508e7b2b0ab
Merge: 95276aa d693506
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Feb 2 10:08:30 2010 -0500
Fancy tooltips
Show tooltips that explain what to do when things are not editable.
To make this less boring, work out how to embed icons in the label.
AUTHORS | 8 ++
src/main.c | 94 ++++++++++++++++++++++++++-
src/um-utils.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/um-utils.h | 9 +++
4 files changed, 310 insertions(+), 2 deletions(-)
---
diff --cc AUTHORS
index eca0fd7,eca0fd7..d11be76
--- a/AUTHORS
+++ b/AUTHORS
@@@ -1,1 -1,1 +1,9 @@@
Matthias Clasen <mclasen redhat com>
++
++The webcam support was done by Bastien Nocera.
++
++The fancy tooltip code was inspired by a gtk-demo example
++by Behdad Esfahbod.
++
++The shortname completion code was adapted from
++similar code in gnome-system-tools by Milan Bouchet-Valat.
diff --cc src/um-utils.c
index 5e29228,3c75cf5..5bb06b7
--- a/src/um-utils.c
+++ b/src/um-utils.c
@@@ -25,4 -25,262 +25,205 @@@
#include <glib/gi18n.h>
#include "um-utils.h"
-#include "um-user-manager.h"
-
-gchar *
-um_compute_short_name (const gchar *name)
-{
- gchar **names;
- gint len;
- gchar *shortname;
- gchar *res;
- gchar *tmp;
- gint i;
- UmUserManager *manager;
- UmUser *user;
-
- /* TODO: pluggable algorithms for this */
- names = g_strsplit (name, " ", 0);
- len = g_strv_length (names);
-
- if (len == 0) {
- shortname = g_strdup ("");
- }
- else if (len == 1) {
- shortname = g_strndup (names[0], 8);
- }
- else {
- gchar *first;
- gchar *suffix;
- first = g_strndup (names[0], 1);
- suffix = g_strndup (names[1], 7);
- shortname = g_strconcat (first, suffix, NULL);
- g_free (first);
- g_free (suffix);
- }
-
- res = g_ascii_strdown (shortname, -1);
-
- g_strfreev (names);
- g_free (shortname);
-
- if (res && res[0]) {
- manager = um_user_manager_ref_default ();
- tmp = g_strdup (res);
- for (i = 2; i < 10; i++) {
- user = um_user_manager_get_user (manager, tmp);
- if (user == NULL) {
- g_free (res);
- res = tmp;
- break;
- }
- g_free (tmp);
- tmp = g_strdup_printf ("%s%d", res, i);
- }
- g_object_unref (manager);
- }
-
- return res;
-}
+ typedef struct {
- const gchar *text;
- const gchar *placeholder_str;
- const gchar *stock_id;
++ gchar *text;
++ gchar *placeholder_str;
++ gchar *stock_id;
+ gunichar placeholder;
+ gulong query_id;
+ } IconShapeData;
+
+ static IconShapeData *
+ icon_shape_data_new (const gchar *text,
+ const gchar *placeholder,
+ const gchar *stock_id)
+ {
+ IconShapeData *data;
+
+ data = g_new0 (IconShapeData, 1);
+
+ data->text = g_strdup (text);
+ data->placeholder_str = g_strdup (placeholder);
+ data->placeholder = g_utf8_get_char_validated (placeholder, -1);
+ data->stock_id = g_strdup (stock_id);
+
+ return data;
+ }
+
+ static void
-icon_shape_data_free (IconShapeData *data)
++icon_shape_data_free (gpointer user_data)
+ {
++ IconShapeData *data = user_data;
++
+ g_free (data->text);
+ g_free (data->placeholder_str);
+ g_free (data->stock_id);
+ g_free (data);
+ }
+
+ static void
+ icon_shape_renderer (cairo_t *cr,
+ PangoAttrShape *attr,
+ gboolean do_path,
+ gpointer user_data)
+ {
+ IconShapeData *data = user_data;
+ gdouble x, y;
+
+ cairo_get_current_point (cr, &x, &y);
+ if (GPOINTER_TO_UINT (attr->data) == data->placeholder) {
+ gdouble ascent;
+ gdouble height;
+ gdouble width;
+ GdkPixbuf *pixbuf;
+
+ ascent = pango_units_to_double (attr->ink_rect.y);
+ height = pango_units_to_double (attr->ink_rect.height);
+ width = pango_units_to_double (attr->ink_rect.width);
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ data->stock_id,
+ (gint)height,
+ GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_USE_BUILTIN,
+ NULL);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_reset_clip (cr);
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y + ascent);
+ cairo_paint (cr);
+ g_object_unref (pixbuf);
+ }
+ }
+
-PangoAttrList *
++static PangoAttrList *
+ create_shape_attr_list_for_layout (PangoLayout *layout,
+ IconShapeData *data)
+ {
+ PangoAttrList *attrs;
+ PangoFontMetrics *metrics;
+ gint ascent, descent;
+ PangoRectangle ink_rect, logical_rect;
+ const gchar *p;
+ const gchar *text;
+ gint placeholder_len;
+
+ /* Get font metrics and prepare fancy shape size */
+ metrics = pango_context_get_metrics (pango_layout_get_context (layout),
+ pango_layout_get_font_description (layout),
+ NULL);
+ ascent = pango_font_metrics_get_ascent (metrics);
+ descent = pango_font_metrics_get_descent (metrics);
+ pango_font_metrics_unref (metrics);
+
+ logical_rect.x = 0;
+ logical_rect.y = - ascent;
+ logical_rect.width = ascent + descent;
+ logical_rect.height = ascent + descent;
+
+ ink_rect = logical_rect;
+
+ attrs = pango_attr_list_new ();
+ text = pango_layout_get_text (layout);
+ placeholder_len = strlen (data->placeholder_str);
+ for (p = text; (p = strstr (p, data->placeholder_str)); p += placeholder_len) {
+ PangoAttribute *attr;
+
+ attr = pango_attr_shape_new_with_data (&ink_rect,
+ &logical_rect,
+ GUINT_TO_POINTER (g_utf8_get_char (p)),
+ NULL, NULL);
+
+ attr->start_index = p - text;
+ attr->end_index = attr->start_index + placeholder_len;
+
+ pango_attr_list_insert (attrs, attr);
+ }
+
+ return attrs;
+ }
+
+ static gboolean
+ query_unlock_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tooltip,
+ GtkTooltip *tooltip,
+ gpointer user_data)
+ {
+ GtkWidget *label;
+ PangoLayout *layout;
+ PangoAttrList *attrs;
+ IconShapeData *data;
+
+ data = g_object_get_data (G_OBJECT (widget), "icon-shape-data");
+ label = g_object_get_data (G_OBJECT (widget), "tooltip-label");
+ if (label == NULL) {
+ label = gtk_label_new (data->text);
+ g_object_ref_sink (label);
+ g_object_set_data_full (G_OBJECT (widget),
+ "tooltip-label", label, g_object_unref);
+ }
+
+ layout = gtk_label_get_layout (GTK_LABEL (label));
+ pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
+ icon_shape_renderer,
+ data, NULL);
+
+ attrs = create_shape_attr_list_for_layout (layout, data);
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+ pango_attr_list_unref (attrs);
+
+ gtk_tooltip_set_custom (tooltip, label);
+
+ return TRUE;
+ }
+
+ void
+ setup_tooltip_with_embedded_icon (GtkWidget *widget,
+ const gchar *text,
+ const gchar *placeholder,
+ const gchar *stock_id)
+ {
- GtkWidget *label;
+ IconShapeData *data;
+
+ data = g_object_get_data (G_OBJECT (widget), "icon-shape-data");
+ if (data) {
+ gtk_widget_set_has_tooltip (widget, FALSE);
+ g_signal_handler_disconnect (widget, data->query_id);
+ g_object_set_data (G_OBJECT (widget), "icon-shape-data", NULL);
+ g_object_set_data (G_OBJECT (widget), "tooltip-label", NULL);
+ }
+
+ if (!placeholder) {
+ gtk_widget_set_tooltip_text (widget, text);
+ return;
+ }
+
+ data = icon_shape_data_new (text, placeholder, stock_id);
+ g_object_set_data_full (G_OBJECT (widget),
+ "icon-shape-data",
+ data,
+ icon_shape_data_free);
+
+ gtk_widget_set_has_tooltip (widget, TRUE);
+ data->query_id = g_signal_connect (widget, "query-tooltip",
+ G_CALLBACK (query_unlock_tooltip), NULL);
+
+ }
+
+ gboolean
+ show_tooltip_now (GtkWidget *widget,
+ GdkEvent *event)
+ {
+ GtkSettings *settings;
+ gint timeout;
+
+ settings = gtk_widget_get_settings (widget);
+
+ g_object_get (settings, "gtk-tooltip-timeout", &timeout, NULL);
+ g_object_set (settings, "gtk-tooltip-timeout", 1, NULL);
+ gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (widget));
+ g_object_set (settings, "gtk-tooltip-timeout", timeout, NULL);
+
+ return FALSE;
+ }
-
diff --cc src/um-utils.h
index 8fc9a80,5d49bf6..dec37d3
--- a/src/um-utils.h
+++ b/src/um-utils.h
@@@ -22,8 -22,20 +22,17 @@@
#ifndef __UM_UTILS_H__
#define __UM_UTILS_H__
+ #include <gtk/gtk.h>
+
G_BEGIN_DECLS
-gchar *um_compute_short_name (const gchar *name);
-
+ void setup_tooltip_with_embedded_icon (GtkWidget *widget,
+ const gchar *text,
+ const gchar *placeholder,
+ const gchar *stock_id);
+ gboolean show_tooltip_now (GtkWidget *widget,
+ GdkEvent *event);
+
-
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]