[gnome-keyring] gcr: Fix up GcrDisplayView bugs and look



commit 8a64c160a7def6363fef332324b6c5a2e28f9e63
Author: Stef Walter <stefw collabora co uk>
Date:   Mon Aug 22 11:05:34 2011 +0200

    gcr: Fix up GcrDisplayView bugs and look
    
     * Separators between items.
     * Clicking details doesn't remove items when more than one
       is displayed.
     * Better spacing.

 gcr/gcr-certificate-renderer.c |    7 +-
 gcr/gcr-display-view.c         |  191 ++++++++++++++++++++++++++++++++--------
 gcr/gcr-display-view.h         |    5 +-
 gcr/gcr-key-renderer.c         |    9 ++-
 4 files changed, 171 insertions(+), 41 deletions(-)
---
diff --git a/gcr/gcr-certificate-renderer.c b/gcr/gcr-certificate-renderer.c
index 558f5ce..5f53cb6 100644
--- a/gcr/gcr-certificate-renderer.c
+++ b/gcr/gcr-certificate-renderer.c
@@ -589,12 +589,14 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
 		return;
 	}
 
-	_gcr_display_view_clear (view, renderer);
+	_gcr_display_view_begin (view, renderer);
 	cert = GCR_CERTIFICATE (self);
 
 	data = gcr_certificate_get_der_data (cert, &n_data);
-	if (!data)
+	if (!data) {
+		_gcr_display_view_end (view, renderer);
 		return;
+	}
 
 	icon = gcr_certificate_get_icon (cert);
 	_gcr_display_view_set_icon (view, GCR_RENDERER (self), icon);
@@ -724,6 +726,7 @@ gcr_certificate_renderer_render (GcrRenderer *renderer, GcrViewer *viewer)
 	}
 
 	egg_asn1x_destroy (asn);
+	_gcr_display_view_end (view, renderer);
 }
 
 static void
diff --git a/gcr/gcr-display-view.c b/gcr/gcr-display-view.c
index 8dd702a..b6cec63 100644
--- a/gcr/gcr-display-view.c
+++ b/gcr/gcr-display-view.c
@@ -64,6 +64,8 @@ struct _GcrDisplayViewPrivate {
 	GtkTextTag *heading_tag;
 	GtkTextTag *monospace_tag;
 	GcrDisplayItem *current_item;
+	gint text_height;
+	GdkCursor *cursor;
 
 	gboolean have_measurements;
 	gint minimal_width;
@@ -135,6 +137,23 @@ ensure_measurements (GcrDisplayView *self)
 }
 
 static void
+ensure_text_height (GcrDisplayView *self)
+{
+	PangoRectangle extents;
+	PangoLayout *layout;
+
+	if (self->pv->text_height > 0)
+		return;
+
+	layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "Wp");
+	pango_layout_get_extents (layout, NULL, &extents);
+	pango_extents_to_pixels (&extents, NULL);
+	g_object_unref (layout);
+
+	self->pv->text_height = extents.height;
+}
+
+static void
 recalculate_and_resize (GcrDisplayView *self)
 {
 	self->pv->have_measurements = FALSE;
@@ -158,7 +177,6 @@ create_tag_table (GcrDisplayView *self)
 	                                    "name", "title",
 	                                    "scale", PANGO_SCALE_LARGE,
 	                                    "right-margin", (ICON_MARGIN * 2) + width,
-	                                    "pixels-above-lines", 9,
 	                                    "pixels-below-lines", 6,
 	                                    "weight", PANGO_WEIGHT_BOLD,
 	                                    NULL);
@@ -221,7 +239,10 @@ style_display_item (GtkWidget *widget, GcrDisplayItem *item)
 
 	gtk_style_context_restore (style);
 
-	gtk_widget_override_background_color (item->details_widget, GTK_STATE_NORMAL, &color);
+	color.red = 255;
+	color.green = 0;
+	color.blue = 0;
+	gtk_widget_override_background_color (item->details_widget, GTK_STATE_FLAG_NORMAL, &color);
 }
 
 static GcrDisplayItem*
@@ -255,13 +276,20 @@ create_display_item (GcrDisplayView *self, GcrRenderer *renderer)
 	item->details_tag = g_object_new (GTK_TYPE_TEXT_TAG, NULL);
 	gtk_text_tag_table_add (tags, item->details_tag);
 
-	/* The mark that determines the beginning of this item, with left gravity. */
+	/*
+	 * Add two zero width spaces that delimit this from later items. The
+	 * item will live between the two zero width spaces.
+	 */
 	gtk_text_buffer_get_end_iter (self->pv->buffer, &iter);
+	gtk_text_buffer_insert (self->pv->buffer, &iter, "\n\n", -1);
+	if (!gtk_text_iter_backward_char (&iter))
+		g_assert_not_reached ();
+
+	/* The mark that determines the beginning of this item, with left gravity. */
 	item->beginning = gtk_text_buffer_create_mark (self->pv->buffer, NULL, &iter, TRUE);
 	g_object_ref (item->beginning);
 
 	/* The mark that determines the end of this item, with right gravity. */
-	gtk_text_buffer_get_end_iter (self->pv->buffer, &iter);
 	item->ending = gtk_text_buffer_create_mark (self->pv->buffer, NULL, &iter, FALSE);
 	g_object_ref (item->ending);
 
@@ -280,6 +308,7 @@ create_display_item (GcrDisplayView *self, GcrRenderer *renderer)
 	gtk_widget_show_all (alignment);
 
 	item->details_widget = gtk_event_box_new ();
+	gtk_event_box_set_visible_window (GTK_EVENT_BOX (item->details_widget), FALSE);
 	gtk_container_add (GTK_CONTAINER (item->details_widget), alignment);
 	g_signal_connect (item->details_widget, "realize", G_CALLBACK (on_expander_realize), NULL);
 	g_object_ref (item->details_widget);
@@ -370,45 +399,103 @@ on_renderer_data_changed (GcrRenderer *renderer, GcrViewer *self)
 }
 
 static void
-paint_widget_icons (GcrDisplayView *self, cairo_t *cr)
+paint_item_icon (GcrDisplayView *self,
+                 GcrDisplayItem *item,
+                 GdkRectangle *visible,
+                 cairo_t *cr)
 {
-	GHashTableIter hit;
-	GtkTextView *view;
-	GdkRectangle visible;
-	GdkRectangle location;
-	GcrDisplayItem *item;
-	gpointer value;
 	GtkTextIter iter;
+	GdkRectangle location;
+	GtkTextView *view;
+
+	if (item->pixbuf == NULL)
+		return;
 
 	view = GTK_TEXT_VIEW (self);
-	gtk_text_view_get_visible_rect (view, &visible);
+	gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->beginning);
+	gtk_text_view_get_iter_location (view, &iter, &location);
 
-	g_hash_table_iter_init (&hit, self->pv->items);
-	while (g_hash_table_iter_next (&hit, NULL, &value)) {
+	location.height = gdk_pixbuf_get_height (item->pixbuf);
+	location.width = gdk_pixbuf_get_width (item->pixbuf);
+	location.x = visible->width - location.width - ICON_MARGIN;
 
-		item = value;
-		if (item->pixbuf == NULL)
-			continue;
+	if (!gdk_rectangle_intersect (visible, &location, NULL))
+		return;
 
-		gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->beginning);
-		gtk_text_view_get_iter_location (view, &iter, &location);
+	gtk_text_view_buffer_to_window_coords (view, GTK_TEXT_WINDOW_TEXT,
+	                                       location.x, location.y,
+	                                       &location.x, &location.y);
 
-		location.height = gdk_pixbuf_get_height (item->pixbuf);
-		location.width = gdk_pixbuf_get_width (item->pixbuf);
-		location.x = visible.width - location.width - ICON_MARGIN;
+	cairo_save (cr);
+	gdk_cairo_set_source_pixbuf (cr, item->pixbuf, location.x, location.y);
+	cairo_rectangle (cr, location.x, location.y, location.width, location.height);
+	cairo_fill (cr);
+	cairo_restore (cr);
+}
 
-		if (!gdk_rectangle_intersect (&visible, &location, NULL))
-			continue;
+static void
+paint_item_border (GcrDisplayView *self,
+                   GcrDisplayItem *item,
+                   GtkStyleContext *context,
+                   GdkRectangle *visible,
+                   gint index,
+                   cairo_t *cr)
+{
+	GdkRGBA color;
+	GtkTextView *view;
+	GtkTextIter iter;
+	GdkRectangle location;
 
-		gtk_text_view_buffer_to_window_coords (view, GTK_TEXT_WINDOW_TEXT,
-		                                       location.x, location.y,
-		                                       &location.x, &location.y);
+	if (index == 0)
+		return;
 
-		cairo_save (cr);
-		gdk_cairo_set_source_pixbuf (cr, item->pixbuf, location.x, location.y);
-		cairo_rectangle (cr, location.x, location.y, location.width, location.height);
-		cairo_fill (cr);
-		cairo_restore (cr);
+	ensure_text_height (self);
+
+	gtk_style_context_get_background_color (context,
+	                                        GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED,
+	                                        &color);
+
+	view = GTK_TEXT_VIEW (self);
+	gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->beginning);
+	gtk_text_view_get_iter_location (view, &iter, &location);
+
+	location.height = 2;
+	location.width = visible->width - (NORMAL_MARGIN * 2);
+	location.x = NORMAL_MARGIN;
+	location.y -= self->pv->text_height / 2;
+
+	if (!gdk_rectangle_intersect (visible, &location, NULL))
+		return;
+
+	gtk_text_view_buffer_to_window_coords (view, GTK_TEXT_WINDOW_TEXT,
+	                                       location.x, location.y,
+	                                       &location.x, &location.y);
+
+	cairo_save (cr);
+	cairo_set_source_rgb (cr, color.red, color.green, color.blue);
+	cairo_set_line_width (cr, 0.5);
+	cairo_move_to (cr, location.x, location.y);
+	cairo_line_to (cr, location.x + location.width, location.y);
+	cairo_stroke (cr);
+	cairo_restore (cr);
+}
+
+static void
+paint_extras (GcrDisplayView *self, cairo_t *cr)
+{
+	GdkRectangle visible;
+	GcrDisplayItem *item;
+	GtkStyleContext *context;
+	guint i;
+
+	gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (self), &visible);
+	context = gtk_widget_get_style_context (GTK_WIDGET (self));
+
+	for (i = 0; i < self->pv->renderers->len; i++) {
+		item = g_hash_table_lookup (self->pv->items, self->pv->renderers->pdata[i]);
+		g_assert (item != NULL);
+		paint_item_icon (self, item, &visible, cr);
+		paint_item_border (self, item, context, &visible, i, cr);
 	}
 }
 
@@ -510,6 +597,8 @@ _gcr_display_view_finalize (GObject *obj)
 	g_object_unref (self->pv->title_tag);
 	self->pv->title_tag = NULL;
 
+	g_clear_object (&self->pv->cursor);
+
 	G_OBJECT_CLASS (_gcr_display_view_parent_class)->finalize (obj);
 }
 
@@ -518,6 +607,7 @@ _gcr_display_view_realize (GtkWidget *widget)
 {
 	GcrDisplayView *self = GCR_DISPLAY_VIEW (widget);
 	GHashTableIter iter;
+	GdkDisplay *display;
 	gpointer value;
 
 	if (GTK_WIDGET_CLASS (_gcr_display_view_parent_class)->realize)
@@ -527,6 +617,14 @@ _gcr_display_view_realize (GtkWidget *widget)
 	g_hash_table_iter_init (&iter, self->pv->items);
 	while (g_hash_table_iter_next (&iter, NULL, &value))
 		style_display_item (widget, value);
+
+	if (!self->pv->cursor) {
+		display = gtk_widget_get_display (GTK_WIDGET (self));
+		self->pv->cursor = gdk_cursor_new_for_display (display, GDK_ARROW);
+	}
+
+	gdk_window_set_cursor (gtk_text_view_get_window (GTK_TEXT_VIEW (self), GTK_TEXT_WINDOW_WIDGET),
+	                       self->pv->cursor);
 }
 
 static gboolean
@@ -567,7 +665,7 @@ _gcr_display_view_draw (GtkWidget *widget, cairo_t *cr)
 
 	window = gtk_text_view_get_window (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_TEXT);
 	if (gtk_cairo_should_draw_window (cr, window))
-		paint_widget_icons (GCR_DISPLAY_VIEW (widget), cr);
+		paint_extras (GCR_DISPLAY_VIEW (widget), cr);
 
 	return handled;
 }
@@ -700,7 +798,8 @@ _gcr_display_view_new (void)
 }
 
 void
-_gcr_display_view_clear (GcrDisplayView *self, GcrRenderer *renderer)
+_gcr_display_view_begin (GcrDisplayView *self,
+                         GcrRenderer *renderer)
 {
 	GtkTextIter start, iter;
 	GcrDisplayItem *item;
@@ -715,15 +814,32 @@ _gcr_display_view_clear (GcrDisplayView *self, GcrRenderer *renderer)
 	gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->ending);
 	gtk_text_buffer_delete (self->pv->buffer, &start, &iter);
 
-	g_return_if_fail (!gtk_text_mark_get_deleted (item->beginning));
-	g_return_if_fail (!gtk_text_mark_get_deleted (item->ending));
-
 	item->extra_tag = NULL;
 	item->field_width = 0;
 	item->details = FALSE;
 }
 
 void
+_gcr_display_view_end (GcrDisplayView *self,
+                       GcrRenderer *renderer)
+{
+	GtkTextIter start, iter;
+	GcrDisplayItem *item;
+
+	g_return_if_fail (GCR_IS_DISPLAY_VIEW (self));
+	item = lookup_display_item (self, renderer);
+	g_return_if_fail (item);
+
+	gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &start, item->beginning);
+	gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->ending);
+
+#if 0
+	if (gtk_text_iter_compare (&start, &iter) != 0)
+		gtk_text_buffer_insert (self->pv->buffer, &iter, "\n", 1);
+#endif
+}
+
+void
 _gcr_display_view_start_details (GcrDisplayView *self, GcrRenderer *renderer)
 {
 	GtkTextChildAnchor *anchor;
@@ -809,6 +925,9 @@ _gcr_display_view_append_value (GcrDisplayView *self, GcrRenderer *renderer, con
 	pango_extents_to_pixels (&extents, NULL);
 	g_object_unref (layout);
 
+	/* An estimate of the text height */
+	self->pv->text_height = extents.height;
+
 	/* Make the tab wide enough to accomodate */
 	if (extents.width > item->field_width) {
 		item->field_width = extents.width + COLUMN_MARGIN;
diff --git a/gcr/gcr-display-view.h b/gcr/gcr-display-view.h
index 5f0f2ee..f697e59 100644
--- a/gcr/gcr-display-view.h
+++ b/gcr/gcr-display-view.h
@@ -55,7 +55,10 @@ GType            _gcr_display_view_get_type                    (void);
 
 GcrDisplayView*  _gcr_display_view_new                         (void);
 
-void             _gcr_display_view_clear                       (GcrDisplayView *self,
+void             _gcr_display_view_begin                       (GcrDisplayView *self,
+                                                                GcrRenderer *renderer);
+
+void             _gcr_display_view_end                         (GcrDisplayView *self,
                                                                 GcrRenderer *renderer);
 
 void             _gcr_display_view_append_value                (GcrDisplayView *self,
diff --git a/gcr/gcr-key-renderer.c b/gcr/gcr-key-renderer.c
index 1b7677d..242d842 100644
--- a/gcr/gcr-key-renderer.c
+++ b/gcr/gcr-key-renderer.c
@@ -258,14 +258,17 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 		return;
 	}
 
-	_gcr_display_view_clear (view, renderer);
+	_gcr_display_view_begin (view, renderer);
 
-	if (!self->pv->attributes)
+	if (!self->pv->attributes) {
+		_gcr_display_view_end (view, renderer);
 		return;
+	}
 
 	if (!gck_attributes_find_ulong (self->pv->attributes, CKA_CLASS, &klass) ||
 	    !gck_attributes_find_ulong (self->pv->attributes, CKA_KEY_TYPE, &key_type)) {
 		g_warning ("private key does not have the CKA_CLASS and CKA_KEY_TYPE attributes");
+		_gcr_display_view_end (view, renderer);
 		return;
 	}
 
@@ -334,6 +337,8 @@ gcr_key_renderer_real_render (GcrRenderer *renderer, GcrViewer *viewer)
 		_gcr_display_view_append_hex (view, renderer, _("SHA256"), fingerprint, n_fingerprint);
 		g_free (fingerprint);
 	}
+
+	_gcr_display_view_end (view, renderer);
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]