gtksourceview r2000 - in trunk: . gtksourceview tests



Author: muntyan
Date: Mon Aug  4 18:39:21 2008
New Revision: 2000
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2000&view=rev

Log:
2008-08-04  Yevgen Muntyan  <muntyan tamu edu>

	Bug 315055 - Change the backgound color of lines containing markers
	New API: gtk_source_view_set_mark_category_background(),
	gtk_source_view_get_mark_category_background(), similar to methods
	for priority and pixbuf.

	* gtksourceview/gtksourceview.c: replaced GtkSourceViewPrivate::current_line_gc
	with current_line_color and current_line_color_set;
	added MarkCategory::background and MarkCategory::background_set;
	removed gtk_source_view_unrealize() since current line GdkGC is removed;
	(source_mark_updated_cb): call gtk_widget_queue_draw() instead of invalidating
	only margin window;
	(gtk_source_view_get_lines): added an array argument to get line heights,
	to use in line background drawing code;
	(gtk_source_view_paint_line_background), (gtk_source_view_paint_marks_background):
	new functions;
	(gtk_source_view_expose): use those; do not draw current line background if
	the widget is insensitive;
	(mark_category_set_background), (gtk_source_view_set_mark_category_background),
	(gtk_source_view_get_mark_category_background): new functions;
	(gtk_source_view_set_mark_category_pixbuf), (gtk_source_view_set_mark_category_priority):
	call gtk_widget_queue_draw() here;
	(update_current_line_color), (gtk_source_view_realize), (gtk_source_view_update_style_scheme):
	only update current line color, no need to fiddle with GdkGC anymore.
	* gtksourceview/gtksourceview.h: gtk_source_view_set_mark_category_background(),
	gtk_source_view_get_mark_category_background().
	* tests/test-widget.c: set background color for marks.



Modified:
   trunk/ChangeLog
   trunk/gtksourceview/gtksourceview.c
   trunk/gtksourceview/gtksourceview.h
   trunk/tests/test-widget.c

Modified: trunk/gtksourceview/gtksourceview.c
==============================================================================
--- trunk/gtksourceview/gtksourceview.c	(original)
+++ trunk/gtksourceview/gtksourceview.c	Mon Aug  4 18:39:21 2008
@@ -117,7 +117,6 @@
 
 	gboolean	 style_scheme_applied;
 	GtkSourceStyleScheme *style_scheme;
-	GdkGC		*current_line_gc;
 	GdkColor        *right_margin_line_color;
 	GdkColor        *right_margin_overlay_color;
 
@@ -125,6 +124,9 @@
 
 	GtkSourceBuffer *source_buffer;
 	gint		 old_lines;
+
+	GdkColor         current_line_color;
+	guint            current_line_color_set : 1;
 };
 
 
@@ -146,6 +148,8 @@
 {
 	gint priority;
 	GdkPixbuf *pixbuf;
+	GdkColor background;
+	guint background_set;
 } MarkCategory;
 
 /* Prototypes. */
@@ -175,6 +179,7 @@
 				       			 gint               first_y,
 				       			 gint               last_y,
 				       			 GArray            *buffer_coords,
+				       			 GArray            *line_heights,
 				       			 GArray            *numbers,
 				       			 gint              *countp);
 static gint     gtk_source_view_expose 			(GtkWidget         *widget,
@@ -208,7 +213,6 @@
 static void     gtk_source_view_style_set               (GtkWidget         *widget,
 							 GtkStyle          *previous_style);
 static void	gtk_source_view_realize			(GtkWidget         *widget);
-static void	gtk_source_view_unrealize		(GtkWidget         *widget);
 static void	gtk_source_view_update_style_scheme	(GtkSourceView     *view);
 
 static MarkCategory *
@@ -239,7 +243,6 @@
 	widget_class->expose_event = gtk_source_view_expose;
 	widget_class->style_set = gtk_source_view_style_set;
 	widget_class->realize = gtk_source_view_realize;
-	widget_class->unrealize = gtk_source_view_unrealize;
 
 	textview_class->populate_popup = gtk_source_view_populate_popup;
 	textview_class->move_cursor = gtk_source_view_move_cursor;
@@ -821,16 +824,9 @@
 			GtkSourceMark	*mark,
 			GtkTextView     *text_view)
 {
-	GdkWindow *margin;
-
-	margin = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_LEFT);
-	if (margin != NULL)
-	{
-		GdkRegion *region;
-
-		region = gdk_drawable_get_visible_region (GDK_DRAWABLE (margin));
-		gdk_window_invalidate_region (margin, region, TRUE);
-	}
+	/* TODO do something more intelligent here, namely
+	 * invalidate only the area under the mark if possible */
+	gtk_widget_queue_draw (GTK_WIDGET (text_view));
 }
 
 static void
@@ -1139,6 +1135,7 @@
 			   gint          first_y,
 			   gint          last_y,
 			   GArray       *buffer_coords,
+			   GArray       *line_heights,
 			   GArray       *numbers,
 			   gint         *countp)
 {
@@ -1149,6 +1146,8 @@
 
 	g_array_set_size (buffer_coords, 0);
 	g_array_set_size (numbers, 0);
+	if (line_heights != NULL)
+		g_array_set_size (line_heights, 0);
 
 	/* Get iter at first y */
 	gtk_text_view_get_line_at_y (text_view, &iter, first_y, NULL);
@@ -1165,6 +1164,8 @@
 		gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
 
 		g_array_append_val (buffer_coords, y);
+		if (line_heights)
+			g_array_append_val (line_heights, height);
 		last_line_num = gtk_text_iter_get_line (&iter);
 		g_array_append_val (numbers, last_line_num);
 
@@ -1188,6 +1189,8 @@
 		if (line_num != last_line_num)
 		{
 			g_array_append_val (buffer_coords, y);
+			if (line_heights)
+				g_array_append_val (line_heights, height);
 			g_array_append_val (numbers, line_num);
 			++count;
 		}
@@ -1364,6 +1367,7 @@
 				   y1,
 				   y2,
 				   pixels,
+				   NULL,
 				   numbers,
 				   &count);
 
@@ -1488,6 +1492,163 @@
 	g_object_unref (G_OBJECT (layout));
 }
 
+static void
+gtk_source_view_paint_line_background (GtkTextView    *text_view,
+				       GdkEventExpose *event,
+				       int             y, /* in buffer coordinates */
+				       int             height,
+				       const GdkColor *color)
+{
+	GdkRectangle visible_rect;
+	GdkRectangle line_rect;
+	gint win_y;
+	gint margin;
+	cairo_t *cr;
+
+	gtk_text_view_get_visible_rect (text_view, &visible_rect);
+
+	gtk_text_view_buffer_to_window_coords (text_view,
+					       GTK_TEXT_WINDOW_TEXT,
+					       visible_rect.x,
+					       y,
+					       &line_rect.x,
+					       &win_y);
+
+	line_rect.x = 0;
+	line_rect.width = visible_rect.width;
+	line_rect.y = win_y;
+	line_rect.height = height;
+
+	if (text_view->hadjustment)
+		margin = gtk_text_view_get_left_margin (text_view) -
+			 (int) text_view->hadjustment->value;
+	else
+		margin = gtk_text_view_get_left_margin (text_view);
+
+	line_rect.x += MAX (0, margin - 1);
+
+	cr = gdk_cairo_create (event->window);
+	gdk_cairo_set_source_color (cr, color);
+	cairo_set_line_width (cr, 1);
+	cairo_rectangle (cr, line_rect.x + .5, line_rect.y + .5,
+			 line_rect.width - 1, line_rect.height - 1);
+	cairo_stroke_preserve (cr);
+	cairo_fill (cr);
+}
+
+static void
+gtk_source_view_paint_marks_background (GtkSourceView  *view,
+					GdkEventExpose *event)
+{
+	GtkTextView *text_view;
+	GArray *numbers;
+	GArray *pixels;
+	GArray *heights;
+	gint y1, y2;
+	gint count;
+	gint i;
+
+	if (view->priv->source_buffer == NULL)
+		return;
+
+	text_view = GTK_TEXT_VIEW (view);
+
+	y1 = event->area.y;
+	y2 = y1 + event->area.height;
+
+	/* get the extents of the line printing */
+	gtk_text_view_window_to_buffer_coords (text_view,
+					       GTK_TEXT_WINDOW_TEXT,
+					       0,
+					       y1,
+					       NULL,
+					       &y1);
+
+	gtk_text_view_window_to_buffer_coords (text_view,
+					       GTK_TEXT_WINDOW_TEXT,
+					       0,
+					       y2,
+					       NULL,
+					       &y2);
+
+	numbers = g_array_new (FALSE, FALSE, sizeof (gint));
+	pixels = g_array_new (FALSE, FALSE, sizeof (gint));
+	heights = g_array_new (FALSE, FALSE, sizeof (gint));
+
+	/* get the line numbers and y coordinates. */
+	gtk_source_view_get_lines (text_view,
+				   y1,
+				   y2,
+				   pixels,
+				   heights,
+				   numbers,
+				   &count);
+
+	if (count == 0)
+	{
+		gint n = 0;
+		gint y;
+		gint height;
+		GtkTextIter iter;
+
+		gtk_text_buffer_get_start_iter (gtk_text_view_get_buffer (text_view), &iter);
+		gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
+
+		g_array_append_val (pixels, y);
+		g_array_append_val (pixels, height);
+		g_array_append_val (numbers, n);
+		count = 1;
+	}
+
+	DEBUG ({
+		g_message ("Painting marks background for line numbers %d - %d",
+			   g_array_index (numbers, gint, 0),
+			   g_array_index (numbers, gint, count - 1));
+	});
+
+	for (i = 0; i < count; ++i)
+	{
+		gint line_to_paint;
+		GSList *marks;
+		GdkColor *background;
+		int priority;
+
+		line_to_paint = g_array_index (numbers, gint, i);
+
+		marks = gtk_source_buffer_get_source_marks_at_line (view->priv->source_buffer,
+								    line_to_paint,
+								    NULL);
+
+		background = NULL;
+		priority = -1;
+
+		while (marks != NULL)
+		{
+			const gchar *category;
+			MarkCategory *cat = NULL;
+			category = gtk_source_mark_get_category (marks->data);
+			if (category != NULL)
+				cat = g_hash_table_lookup (view->priv->mark_categories, category);
+			if (cat != NULL && cat->background_set && cat->priority > priority)
+			{
+				background = &cat->background;
+				priority = cat->priority;
+			}
+			marks = g_slist_delete_link (marks, marks);
+		}
+
+		if (background != NULL)
+			gtk_source_view_paint_line_background (text_view, event,
+							       g_array_index (pixels, gint, i),
+							       g_array_index (heights, gint, i),
+							       background);
+	}
+
+	g_array_free (heights, TRUE);
+	g_array_free (pixels, TRUE);
+	g_array_free (numbers, TRUE);
+}
+
 static gint
 gtk_source_view_expose (GtkWidget      *widget,
 			GdkEventExpose *event)
@@ -1559,67 +1720,29 @@
 				gdk_window_invalidate_rect (w, NULL, FALSE);
 		}
 
-		if (view->priv->highlight_current_line &&
+		if (GTK_WIDGET_IS_SENSITIVE(view) && view->priv->highlight_current_line &&
 		    (event->window == gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT)))
 		{
-			GdkRectangle visible_rect;
-			GdkRectangle redraw_rect;
 			GtkTextIter cur;
-			gint y;
-			gint height;
-			gint win_y;
-			GdkGC *gc;
-			gint margin;
+			gint y, height;
+			GdkColor *color;
 
 			gtk_text_buffer_get_iter_at_mark (text_view->buffer,
 							  &cur,
 							  gtk_text_buffer_get_insert (text_view->buffer));
-
 			gtk_text_view_get_line_yrange (text_view, &cur, &y, &height);
 
-			gtk_text_view_get_visible_rect (text_view, &visible_rect);
-
-			gtk_text_view_buffer_to_window_coords (text_view,
-						       GTK_TEXT_WINDOW_TEXT,
-						       visible_rect.x,
-						       visible_rect.y,
-						       &redraw_rect.x,
-						       &redraw_rect.y);
-
-			gtk_text_view_buffer_to_window_coords (text_view,
-						       GTK_TEXT_WINDOW_TEXT,
-						       0,
-						       y,
-						       NULL,
-						       &win_y);
-
-			redraw_rect.width = visible_rect.width;
-			redraw_rect.height = visible_rect.height;
-
-			if (view->priv->current_line_gc)
-				gc = view->priv->current_line_gc;
-			else
-				gc = widget->style->bg_gc[GTK_WIDGET_STATE (widget)];
-
-			if (text_view->hadjustment)
-			{
-				margin = gtk_text_view_get_left_margin (text_view) -
-					 (int) text_view->hadjustment->value;
-			}
+			if (view->priv->current_line_color_set)
+				color = &view->priv->current_line_color;
 			else
-			{
-				margin = gtk_text_view_get_left_margin (text_view);
-			}
+				color = &widget->style->bg[GTK_WIDGET_STATE (widget)];
 
-			gdk_draw_rectangle (event->window,
-					    gc,
-					    TRUE,
-					    redraw_rect.x + MAX (0, margin - 1),
-					    win_y,
-					    redraw_rect.width,
-					    height);
+			gtk_source_view_paint_line_background (text_view, event, y, height, color);
 		}
 
+		if (event->window == gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT))
+			gtk_source_view_paint_marks_background (view, event);
+
 		/* Have GtkTextView draw the text first. */
 		if (GTK_WIDGET_CLASS (gtk_source_view_parent_class)->expose_event)
 			event_handled =
@@ -2062,6 +2185,20 @@
 	return view->priv->indent_width;
 }
 
+static void
+mark_category_set_background (MarkCategory *cat, const GdkColor *background)
+{
+	if (background != NULL)
+	{
+		cat->background_set = TRUE;
+		cat->background = *background;
+	}
+	else
+	{
+		cat->background_set = FALSE;
+	}
+}
+
 static MarkCategory *
 mark_category_new (gint priority, GdkPixbuf *pixbuf)
 {
@@ -2155,6 +2292,9 @@
 			cat->pixbuf = NULL;
 		}
 	}
+
+	/* We may need to redraw the margin now */
+	gtk_widget_queue_draw (GTK_WIDGET (view));
 }
 
 /**
@@ -2185,6 +2325,80 @@
 }
 
 /**
+ * gtk_source_view_set_mark_category_background:
+ * @view: a #GtkSourceView.
+ * @category: a mark category.
+ * @color: background color or %NULL to unset it.
+ *
+ * Sets given background @color for mark @category.
+ * If @color is #NULL, the background color is unset.
+ *
+ * Since: 2.4
+ */
+void
+gtk_source_view_set_mark_category_background (GtkSourceView  *view,
+					      const gchar    *category,
+					      const GdkColor *color)
+{
+	MarkCategory *cat;
+
+	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
+	g_return_if_fail (category != NULL);
+
+	cat = g_hash_table_lookup (view->priv->mark_categories, category);
+
+	if (color != NULL && cat == NULL)
+	{
+		cat = mark_category_new (0, NULL);
+		g_hash_table_insert (view->priv->mark_categories,
+				     g_strdup (category),
+				     cat);
+	}
+
+	if (cat != NULL)
+		mark_category_set_background (cat, color);
+
+	/* We may need to redraw the text background now */
+	gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
+/**
+ * gtk_source_view_get_mark_category_background:
+ * @view: a #GtkSourceView.
+ * @category: a mark category.
+ * @dest: destination #GdkColor structure to fill in.
+ *
+ * Gets the background color associated with given @category.
+ *
+ * Return value: %TRUE if background color for @category was set
+ * and @dest is set to a valid color, or %FALSE otherwise.
+ *
+ * Since: 2.4
+ */
+gboolean
+gtk_source_view_get_mark_category_background (GtkSourceView *view,
+					      const gchar   *category,
+					      GdkColor      *dest)
+{
+	MarkCategory *cat;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), FALSE);
+	g_return_val_if_fail (category != NULL, FALSE);
+	g_return_val_if_fail (dest != NULL, FALSE);
+
+	cat = g_hash_table_lookup (view->priv->mark_categories, category);
+	if (cat != NULL && cat->background_set)
+	{
+		*dest = cat->background;
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
+/**
  * gtk_source_view_set_mark_category_priority:
  * @view: a #GtkSourceView.
  * @category: a mark category.
@@ -2216,6 +2430,9 @@
 	}
 	else
 		cat->priority = priority;
+
+	/* We may need to redraw now, if the priorities affect appearance */
+	gtk_widget_queue_draw (GTK_WIDGET (view));
 }
 
 /**
@@ -3274,31 +3491,11 @@
 }
 
 static void
-update_current_line_gc (GtkSourceView *view)
+update_current_line_color (GtkSourceView *view)
 {
-	GdkColor color;
-	GtkWidget *widget = GTK_WIDGET (view);
-
-	if (!GTK_WIDGET_REALIZED (view))
-		return;
-
-	if (view->priv->current_line_gc)
-	{
-		g_object_unref (view->priv->current_line_gc);
-		view->priv->current_line_gc = NULL;
-	}
-
-	if (view->priv->style_scheme &&
-	    _gtk_source_style_scheme_get_current_line_color (view->priv->style_scheme, &color))
-	{
-		GdkGCValues values;
-		gdk_colormap_alloc_color (gtk_widget_get_colormap (widget),
-					  &color, TRUE, TRUE);
-		values.foreground = color;
-		view->priv->current_line_gc = gdk_gc_new_with_values (widget->window,
-								      &values,
-								      GDK_GC_FOREGROUND);
-	}
+	view->priv->current_line_color_set =
+		_gtk_source_style_scheme_get_current_line_color (view->priv->style_scheme,
+								 &view->priv->current_line_color);
 }
 
 static void
@@ -3377,23 +3574,11 @@
 		view->priv->style_scheme_applied = TRUE;
 	}
 
-	update_current_line_gc (view);
+	update_current_line_color (view);
 	update_right_margin_colors (view);
 }
 
 static void
-gtk_source_view_unrealize (GtkWidget *widget)
-{
-	GtkSourceView *view = GTK_SOURCE_VIEW (widget);
-
-	if (view->priv->current_line_gc)
-		g_object_unref (view->priv->current_line_gc);
-	view->priv->current_line_gc = NULL;
-
-	GTK_WIDGET_CLASS (gtk_source_view_parent_class)->unrealize (widget);
-}
-
-static void
 gtk_source_view_update_style_scheme (GtkSourceView *view)
 {
 	GtkSourceStyleScheme *new_scheme;
@@ -3417,7 +3602,7 @@
 		if (GTK_WIDGET_REALIZED (view))
 		{
 			_gtk_source_style_scheme_apply (new_scheme, GTK_WIDGET (view));
-			update_current_line_gc (view);
+			update_current_line_color (view);
 			update_right_margin_colors (view);
 			view->priv->style_scheme_applied = TRUE;
 		}

Modified: trunk/gtksourceview/gtksourceview.h
==============================================================================
--- trunk/gtksourceview/gtksourceview.h	(original)
+++ trunk/gtksourceview/gtksourceview.h	Mon Aug  4 18:39:21 2008
@@ -146,6 +146,15 @@
 							(GtkSourceView   *view,
 				       			 const gchar     *category);
 
+void             gtk_source_view_set_mark_category_background
+							(GtkSourceView   *view,
+							 const gchar     *category,
+							 const GdkColor  *color);
+gboolean         gtk_source_view_get_mark_category_background
+							(GtkSourceView   *view,
+							 const gchar     *category,
+							 GdkColor        *dest);
+
 void             gtk_source_view_set_mark_category_priority
 							(GtkSourceView   *view,
 							 const gchar     *category,

Modified: trunk/tests/test-widget.c
==============================================================================
--- trunk/tests/test-widget.c	(original)
+++ trunk/tests/test-widget.c	Mon Aug  4 18:39:21 2008
@@ -1332,6 +1332,9 @@
 	error = NULL;
 	if ((pixbuf = gdk_pixbuf_new_from_file (TOP_SRCDIR "/tests/gnome-gmush.png", &error)))
 	{
+		GdkColor color;
+		gdk_color_parse ("lightgreen", &color);
+		gtk_source_view_set_mark_category_background (GTK_SOURCE_VIEW (view), MARK_TYPE_1, &color);
 		gtk_source_view_set_mark_category_pixbuf (GTK_SOURCE_VIEW (view), MARK_TYPE_1, pixbuf);
 		gtk_source_view_set_mark_category_priority (GTK_SOURCE_VIEW (view), MARK_TYPE_1, 1);
 		g_object_unref (pixbuf);
@@ -1346,6 +1349,9 @@
 	error = NULL;
 	if ((pixbuf = gdk_pixbuf_new_from_file (TOP_SRCDIR "/tests/apple-red.png", &error)))
 	{
+		GdkColor color;
+		gdk_color_parse ("pink", &color);
+		gtk_source_view_set_mark_category_background (GTK_SOURCE_VIEW (view), MARK_TYPE_2, &color);
 		gtk_source_view_set_mark_category_pixbuf (GTK_SOURCE_VIEW (view), MARK_TYPE_2, pixbuf);
 		gtk_source_view_set_mark_category_priority (GTK_SOURCE_VIEW (view), MARK_TYPE_2, 2);
 		g_object_unref (pixbuf);



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