[accounts-dialog: 1/2] Some tooltip trickery
- From: Matthias Clasen <matthiasc src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [accounts-dialog: 1/2] Some tooltip trickery
- Date: Tue, 2 Feb 2010 15:46:05 +0000 (UTC)
commit d6935060118cb232422aa0afe6f03902345a75b6
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Feb 1 22:18:25 2010 -0500
Some tooltip trickery
src/main.c | 94 +++++++++++++++++++++++++-
src/um-utils.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/um-utils.h | 10 +++
3 files changed, 304 insertions(+), 2 deletions(-)
---
diff --git a/src/main.c b/src/main.c
index 4440a82..aff24bd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -53,6 +53,7 @@
#include "um-password-dialog.h"
#include "um-photo-dialog.h"
#include "um-fingerprint-dialog.h"
+#include "um-utils.h"
#include "gdm-languages.h"
@@ -1118,6 +1119,7 @@ lockbutton_changed (PolkitLockButton *button,
gboolean is_authorized;
gboolean self_selected;
UmUser *user;
+ GtkWidget *widget;
user = get_selected_user (d);
if (!user) {
@@ -1127,8 +1129,29 @@ lockbutton_changed (PolkitLockButton *button,
is_authorized = polkit_lock_button_get_is_authorized (button);
self_selected = um_user_get_uid (user) == geteuid ();
- gtk_widget_set_sensitive (get_widget (d, "add-user-button"), is_authorized);
- gtk_widget_set_sensitive (get_widget (d, "delete-user-button"), is_authorized && !self_selected);
+ widget = get_widget (d, "add-user-button");
+ gtk_widget_set_sensitive (widget, is_authorized);
+ if (is_authorized) {
+ setup_tooltip_with_embedded_icon (widget, _("Create a user"), NULL, NULL);
+ }
+ else {
+ setup_tooltip_with_embedded_icon (widget,
+ _("To create a user,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ }
+
+ widget = get_widget (d, "delete-user-button");
+ gtk_widget_set_sensitive (widget, is_authorized && !self_selected);
+ if (is_authorized) {
+ setup_tooltip_with_embedded_icon (widget, _("Delete the selected user"), NULL, NULL);
+ }
+ else {
+ setup_tooltip_with_embedded_icon (widget,
+ _("To delete the selected user,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ }
if (is_authorized) {
if (gtk_notebook_get_current_page (GTK_NOTEBOOK (get_widget (d, "account-type-notebook"))) == 0) {
@@ -1336,17 +1359,57 @@ setup_main_window (UserAccountDialog *d)
button = get_widget (d, "user-list-button");
g_signal_connect (button, "toggled", G_CALLBACK (toggle_user_list), d);
+ button = get_widget (d, "user-icon-nonbutton");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
+ button = get_widget (d, "full-name-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "full-name-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_name), d);
+ button = get_widget (d, "account-type-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To change the account type,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "account-type-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_account_type_start), d);
button = get_widget (d, "account-type-combo");
g_signal_connect (button, "changed", G_CALLBACK (account_type_changed), d);
+ button = get_widget (d, "account-password-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "account-password-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_password), d);
+ button = get_widget (d, "account-email-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "account-email-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_email_start), d);
button = get_widget (d, "account-email-entry");
@@ -1354,6 +1417,14 @@ setup_main_window (UserAccountDialog *d)
g_signal_connect (button, "focus-out-event", G_CALLBACK (change_email_focus_out), d);
g_signal_connect (button, "key-press-event", G_CALLBACK (change_email_key_press), d);
+ button = get_widget (d, "account-language-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "account-language-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_language_start), d);
button = get_widget (d, "account-language-combo");
@@ -1363,6 +1434,14 @@ setup_main_window (UserAccountDialog *d)
/* ugly hack to catch the combo boxes losing focus */
g_signal_connect (window, "set-focus", G_CALLBACK (focus_moved), d);
+ button = get_widget (d, "account-location-value-label");
+ setup_tooltip_with_embedded_icon (button,
+ _("To make changes,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ g_signal_connect (button, "button-release-event",
+ G_CALLBACK (show_tooltip_now), NULL);
+
button = get_widget (d, "account-location-button");
g_signal_connect (button, "clicked", G_CALLBACK (change_location_start), d);
button = get_widget (d, "account-location-entry");
@@ -1382,6 +1461,17 @@ setup_main_window (UserAccountDialog *d)
G_CALLBACK (lockbutton_changed), d);
lockbutton_changed (POLKIT_LOCK_BUTTON (button), d);
d->lock_button = button;
+
+ button = get_widget (d, "add-user-button");
+ setup_tooltip_with_embedded_icon (button,
+ _("To create a user,\nclick the * icon first"),
+ "*",
+ "stock_lock");
+ button = get_widget (d, "delete-user-button");
+ setup_tooltip_with_embedded_icon (button,
+ _("To delete the selected user,\nclick the * icon first"),
+ "*",
+ "stock_lock");
}
static void
diff --git a/src/um-utils.c b/src/um-utils.c
index 26d7702..3c75cf5 100644
--- a/src/um-utils.c
+++ b/src/um-utils.c
@@ -82,3 +82,205 @@ um_compute_short_name (const gchar *name)
return res;
}
+
+typedef struct {
+ const gchar *text;
+ const gchar *placeholder_str;
+ const 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)
+{
+ 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 *
+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 --git a/src/um-utils.h b/src/um-utils.h
index 6788107..5d49bf6 100644
--- a/src/um-utils.h
+++ b/src/um-utils.h
@@ -22,10 +22,20 @@
#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]