[gtksourceview] Improved gutter support
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview] Improved gutter support
- Date: Fri, 26 Nov 2010 21:24:20 +0000 (UTC)
commit 494ec0ca9a066b7790dc6300d3db5270fe340686
Author: Jesse van den Kieboom <jesse icecrew nl>
Date: Mon Oct 11 07:33:20 2010 +0200
Improved gutter support
We are no longer using GtkCellRenderer for rendering in the gutter since it
had some limitations (in particular for sizing and accurate user control).
gtksourceview/Makefile.am | 17 +-
gtksourceview/gtksourcegutter.c | 1631 ++++++++++++++++---------
gtksourceview/gtksourcegutter.h | 70 +-
gtksourceview/gtksourcegutterrenderer.c | 1227 +++++++++++++++++++
gtksourceview/gtksourcegutterrenderer.h | 218 ++++
gtksourceview/gtksourcegutterrendererlines.c | 344 ++++++
gtksourceview/gtksourcegutterrendererlines.h | 66 +
gtksourceview/gtksourcegutterrenderermarks.c | 454 +++++++
gtksourceview/gtksourcegutterrenderermarks.h | 66 +
gtksourceview/gtksourcegutterrendererpixbuf.c | 477 ++++++++
gtksourceview/gtksourcegutterrendererpixbuf.h | 95 ++
gtksourceview/gtksourcegutterrenderertext.c | 432 +++++++
gtksourceview/gtksourcegutterrenderertext.h | 83 ++
gtksourceview/gtksourcemarkcategory.c | 571 +++++++++
gtksourceview/gtksourcemarkcategory.h | 109 ++
gtksourceview/gtksourcepixbufhelper.c | 352 ++++++
gtksourceview/gtksourcepixbufhelper.h | 62 +
gtksourceview/gtksourceview-marshal.list | 5 +
gtksourceview/gtksourceview.c | 1381 +++------------------
gtksourceview/gtksourceview.h | 58 +-
tests/test-widget.c | 58 +-
21 files changed, 5855 insertions(+), 1921 deletions(-)
---
diff --git a/gtksourceview/Makefile.am b/gtksourceview/Makefile.am
index 77710c0..0b2f7b0 100644
--- a/gtksourceview/Makefile.am
+++ b/gtksourceview/Makefile.am
@@ -29,9 +29,13 @@ libgtksourceview_headers = \
gtksourcecompletionproposal.h \
gtksourcecompletionprovider.h \
gtksourcegutter.h \
+ gtksourcegutterrenderer.h \
+ gtksourcegutterrenderertext.h \
+ gtksourcegutterrendererpixbuf.h \
gtksourcelanguage.h \
gtksourcelanguagemanager.h \
gtksourcemark.h \
+ gtksourcemarkcategory.h \
gtksourceprintcompositor.h \
gtksourcestyle.h \
gtksourcestylescheme.h \
@@ -52,7 +56,11 @@ NOINST_H_FILES = \
gtksourceundomanagerdefault.h \
gtksourceview-i18n.h \
gtksourceview-utils.h \
- gtktextregion.h
+ gtktextregion.h \
+ gtksourcepixbufhelper.h \
+ gtksourcegutterrendererlines.h \
+ gtksourcegutterrenderermarks.h \
+ gtksourcemarkcategory.h
libgtksourceview_c_files = \
gtksourcebuffer.c \
@@ -67,6 +75,13 @@ libgtksourceview_c_files = \
gtksourcecontextengine.c \
gtksourceengine.c \
gtksourcegutter.c \
+ gtksourcegutterrenderer.c \
+ gtksourcegutterrenderertext.c \
+ gtksourcegutterrendererpixbuf.c \
+ gtksourcegutterrendererlines.c \
+ gtksourcegutterrenderermarks.c \
+ gtksourcemarkcategory.c \
+ gtksourcepixbufhelper.c \
gtksourcelanguage.c \
gtksourcelanguagemanager.c \
gtksourcelanguage-parser-1.c \
diff --git a/gtksourceview/gtksourcegutter.c b/gtksourceview/gtksourcegutter.c
index 72ad148..26e76c9 100644
--- a/gtksourceview/gtksourcegutter.c
+++ b/gtksourceview/gtksourcegutter.c
@@ -23,6 +23,9 @@
#include "gtksourceview.h"
#include "gtksourceview-i18n.h"
#include "gtksourceview-marshal.h"
+#include "gtksourcegutterrenderer.h"
+
+#include <gobject/gvaluecollector.h>
/**
* SECTION:gutter
@@ -32,27 +35,17 @@
*
* The #GtkSourceGutter object represents the left and right gutters of the text
* view. It is used by #GtkSourceView to draw the line numbers and category
- * marks that might be present on a line. By packing additional #GtkCellRenderer
+ * marks that might be present on a line. By packing additional #GtkSourceGutterRenderer
* objects in the gutter, you can extend the gutter with your own custom
* drawings.
*
* The gutter works very much the same way as cells rendered in a #GtkTreeView.
* The concept is similar, with the exception that the gutter does not have an
- * underlying #GtkTreeModel. Instead, you should use
- * #gtk_source_gutter_set_cell_data_func to set a callback to fill in any of the
- * cell renderers properties, given the line for which the cell is to be
- * rendered. Renderers are inserted into the gutter at a certain position. The
- * builtin line number renderer is at position
-
+ * underlying #GtkTreeModel. The builtin line number renderer is at position
* #GTK_SOURCE_VIEW_GUTTER_POSITION_LINES (-30) and the marks renderer is at
* #GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS (-20). You can use these values to
- * position custom renderers accordingly. The width of a cell renderer can be
- * specified as either fixed (using
-
- * #gtk_cell_renderer_set_fixed_size) or dynamic, in which case you
- * <emphasis>must</emphasis> set #gtk_source_gutter_set_cell_size_func. This
- * callback is used to set the properties of the renderer such that
- * #gtk_cell_size_request_get_size yields the maximum width of the cell.
+ * position custom renderers accordingly.
+ *
*/
#define GTK_SOURCE_GUTTER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER, GtkSourceGutterPrivate))
@@ -62,31 +55,22 @@ enum
{
PROP_0,
PROP_VIEW,
- PROP_WINDOW_TYPE
+ PROP_WINDOW_TYPE,
+ PROP_XPAD,
+ PROP_YPAD
};
-/* Signals */
-enum
-{
- CELL_ACTIVATED,
- QUERY_TOOLTIP,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = {0,};
-
typedef struct
{
- GtkCellRenderer *renderer;
- gint position;
+ GtkSourceGutterRenderer *renderer;
- GtkSourceGutterDataFunc data_func;
- gpointer data_func_data;
- GDestroyNotify data_func_destroy;
+ gint prelit;
+ gint position;
- GtkSourceGutterSizeFunc size_func;
- gpointer size_func_data;
- GDestroyNotify size_func_destroy;
+ guint queue_draw_handler;
+ guint size_changed_handler;
+ guint notify_xpad_handler;
+ guint notify_ypad_handler;
} Renderer;
enum
@@ -97,6 +81,7 @@ enum
ENTER_NOTIFY_EVENT,
LEAVE_NOTIFY_EVENT,
QUERY_TOOLTIP_EVENT,
+ REALIZE,
LAST_EXTERNAL_SIGNAL
};
@@ -104,9 +89,17 @@ struct _GtkSourceGutterPrivate
{
GtkSourceView *view;
GtkTextWindowType window_type;
+ GtkOrientation orientation;
+
gint size;
GList *renderers;
+
+ gint xpad;
+ gint ypad;
+
guint signals[LAST_EXTERNAL_SIGNAL];
+
+ guint is_drawing : 1;
};
G_DEFINE_TYPE (GtkSourceGutter, gtk_source_gutter, G_TYPE_OBJECT)
@@ -139,21 +132,74 @@ static gboolean on_view_query_tooltip (GtkSourceView *view,
GtkTooltip *tooltip,
GtkSourceGutter *gutter);
+static void do_redraw (GtkSourceGutter *gutter);
+static void update_gutter_size (GtkSourceGutter *gutter);
+
static void
-view_notify (GtkSourceGutter *gutter,
- gpointer where_the_object_was)
+on_renderer_size_changed (GtkSourceGutterRenderer *renderer,
+ GParamSpec *spec,
+ GtkSourceGutter *gutter)
{
- gutter->priv->view = NULL;
+ update_gutter_size (gutter);
+}
+
+static void
+on_renderer_queue_draw (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutter *gutter)
+{
+ do_redraw (gutter);
+}
+
+static void
+on_renderer_notify_padding (GtkSourceGutterRenderer *renderer,
+ GParamSpec *spec,
+ GtkSourceGutter *gutter)
+{
+ update_gutter_size (gutter);
}
static Renderer *
-renderer_new (GtkCellRenderer *renderer,
- gint position)
+renderer_new (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ guint num_parameters,
+ GParameter *parameters)
{
Renderer *ret = g_slice_new0 (Renderer);
- ret->renderer = g_object_ref_sink (renderer);
+ ret->renderer = g_object_newv (gtype, num_parameters, parameters);
+
+ if (G_IS_INITIALLY_UNOWNED (ret->renderer))
+ {
+ g_object_ref_sink (ret->renderer);
+ }
+
ret->position = position;
+ ret->prelit = -1;
+
+ ret->size_changed_handler =
+ g_signal_connect (ret->renderer,
+ "notify::size",
+ G_CALLBACK (on_renderer_size_changed),
+ gutter);
+
+ ret->queue_draw_handler =
+ g_signal_connect (ret->renderer,
+ "queue-draw",
+ G_CALLBACK (on_renderer_queue_draw),
+ gutter);
+
+ ret->notify_xpad_handler =
+ g_signal_connect (ret->renderer,
+ "notify::xpad",
+ G_CALLBACK (on_renderer_notify_padding),
+ gutter);
+
+ ret->notify_ypad_handler =
+ g_signal_connect (ret->renderer,
+ "notify::ypad",
+ G_CALLBACK (on_renderer_notify_padding),
+ gutter);
return ret;
}
@@ -161,15 +207,17 @@ renderer_new (GtkCellRenderer *renderer,
static void
renderer_free (Renderer *renderer)
{
- if (renderer->data_func_destroy && renderer->data_func_data)
- {
- renderer->data_func_destroy (renderer->data_func_data);
- }
+ g_signal_handler_disconnect (renderer->renderer,
+ renderer->queue_draw_handler);
- if (renderer->size_func_destroy && renderer->size_func_data)
- {
- renderer->size_func_destroy (renderer->size_func_data);
- }
+ g_signal_handler_disconnect (renderer->renderer,
+ renderer->size_changed_handler);
+
+ g_signal_handler_disconnect (renderer->renderer,
+ renderer->notify_xpad_handler);
+
+ g_signal_handler_disconnect (renderer->renderer,
+ renderer->notify_ypad_handler);
g_object_unref (renderer->renderer);
g_slice_free (Renderer, renderer);
@@ -198,10 +246,6 @@ gtk_source_gutter_dispose (GObject *object)
gutter->priv->signals[i]);
}
- g_object_weak_unref (G_OBJECT (gutter->priv->view),
- (GWeakNotify)view_notify,
- gutter);
-
gutter->priv->view = NULL;
}
@@ -220,63 +264,76 @@ gtk_source_gutter_get_property (GObject *object,
{
case PROP_VIEW:
g_value_set_object (value, self->priv->view);
- break;
+ break;
case PROP_WINDOW_TYPE:
g_value_set_enum (value, self->priv->window_type);
- break;
+ break;
+ case PROP_XPAD:
+ g_value_set_int (value, self->priv->xpad);
+ break;
+ case PROP_YPAD:
+ g_value_set_int (value, self->priv->ypad);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ break;
}
}
static void
+on_view_realize (GtkSourceView *view,
+ GtkSourceGutter *gutter)
+{
+ update_gutter_size (gutter);
+}
+
+static void
set_view (GtkSourceGutter *gutter,
GtkSourceView *view)
{
gutter->priv->view = view;
- gutter->priv->size = -1;
-
- g_object_weak_ref (G_OBJECT (view),
- (GWeakNotify)view_notify,
- gutter);
-
gutter->priv->signals[DRAW] =
g_signal_connect (view,
- "draw",
- G_CALLBACK (on_view_draw),
- gutter);
+ "draw",
+ G_CALLBACK (on_view_draw),
+ gutter);
gutter->priv->signals[MOTION_NOTIFY_EVENT] =
g_signal_connect (view,
- "motion-notify-event",
- G_CALLBACK (on_view_motion_notify_event),
- gutter);
+ "motion-notify-event",
+ G_CALLBACK (on_view_motion_notify_event),
+ gutter);
gutter->priv->signals[ENTER_NOTIFY_EVENT] =
g_signal_connect (view,
- "enter-notify-event",
- G_CALLBACK (on_view_enter_notify_event),
- gutter);
+ "enter-notify-event",
+ G_CALLBACK (on_view_enter_notify_event),
+ gutter);
gutter->priv->signals[LEAVE_NOTIFY_EVENT] =
g_signal_connect (view,
- "leave-notify-event",
- G_CALLBACK (on_view_leave_notify_event),
- gutter);
+ "leave-notify-event",
+ G_CALLBACK (on_view_leave_notify_event),
+ gutter);
gutter->priv->signals[BUTTON_PRESS_EVENT] =
g_signal_connect (view,
- "button-press-event",
- G_CALLBACK (on_view_button_press_event),
- gutter);
+ "button-press-event",
+ G_CALLBACK (on_view_button_press_event),
+ gutter);
gutter->priv->signals[QUERY_TOOLTIP_EVENT] =
g_signal_connect (view,
- "query-tooltip",
- G_CALLBACK (on_view_query_tooltip),
- gutter);
+ "query-tooltip",
+ G_CALLBACK (on_view_query_tooltip),
+ gutter);
+
+ gutter->priv->signals[REALIZE] =
+ g_signal_connect (view,
+ "realize",
+ G_CALLBACK (on_view_realize),
+ gutter);
}
static void
@@ -287,40 +344,109 @@ do_redraw (GtkSourceGutter *gutter)
window = gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->priv->view),
gutter->priv->window_type);
- if (window)
+ if (window && !gutter->priv->is_drawing)
{
gdk_window_invalidate_rect (window, NULL, FALSE);
}
}
-static void
-revalidate_size (GtkSourceGutter *gutter)
+static gint
+calculate_gutter_size (GtkSourceGutter *gutter,
+ GArray *sizes)
{
- GdkWindow *window;
+ GList *item;
+ gint total_width = 0;
- window = gtk_source_gutter_get_window (gutter);
+ /* Calculate size */
+ for (item = gutter->priv->renderers; item; item = g_list_next (item))
+ {
+ Renderer *renderer = item->data;
+ gint width;
+
+ if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
+ {
+ width = 0;
+ }
+ else
+ {
+ gint xpad;
+ gint size;
+
+ size = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+ gtk_source_gutter_renderer_get_padding (renderer->renderer,
+ &xpad,
+ NULL);
+
+ width = size + 2 * xpad;
+ }
+
+ if (sizes)
+ {
+ g_array_append_val (sizes, width);
+ }
+
+ total_width += width + gutter->priv->xpad;
+ }
- if (!window && gutter->priv->renderers)
+ if (gutter->priv->renderers)
{
- /* Make window visible by setting its size to minimum size,
- actual size will be calculated in draw */
- gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
- gutter->priv->window_type,
- 1);
- gutter->priv->size = -1;
+ total_width += gutter->priv->xpad;
}
- else if (window && !gutter->priv->renderers)
+
+ return total_width;
+}
+
+static void
+update_gutter_size (GtkSourceGutter *gutter)
+{
+ gint width;
+
+ width = calculate_gutter_size (gutter, NULL);
+
+ gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
+ gutter->priv->window_type,
+ width);
+}
+
+static gboolean
+set_padding (GtkSourceGutter *gutter,
+ gint *field,
+ gint padding,
+ const gchar *name,
+ gboolean resize)
+{
+ if (*field == padding || padding < 0)
{
- /* Make window invisible by setting size to 0 */
- gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
- gutter->priv->window_type,
- 0);
+ return FALSE;
}
- else if (window)
+
+ *field = padding;
+
+ g_object_notify (G_OBJECT (gutter), name);
+
+ if (resize)
{
- /* Redraw the window. Actual size will be calculated in draw */
- do_redraw (gutter);
+ update_gutter_size (gutter);
}
+
+ return TRUE;
+}
+
+static gboolean
+set_xpad (GtkSourceGutter *gutter,
+ gint xpad,
+ gboolean resize)
+{
+ return set_padding (gutter, &gutter->priv->xpad, xpad, "xpad", resize);
+}
+
+static gboolean
+set_ypad (GtkSourceGutter *gutter,
+ gint ypad,
+ gboolean resize)
+{
+ return set_padding (gutter, &gutter->priv->ypad, ypad, "ypad", resize);
}
static void
@@ -335,14 +461,37 @@ gtk_source_gutter_set_property (GObject *object,
{
case PROP_VIEW:
set_view (self, GTK_SOURCE_VIEW (g_value_get_object (value)));
-
- break;
+ break;
case PROP_WINDOW_TYPE:
self->priv->window_type = g_value_get_enum (value);
- break;
+ break;
+ case PROP_XPAD:
+ set_xpad (self, g_value_get_int (value), TRUE);
+ break;
+ case PROP_YPAD:
+ set_ypad (self, g_value_get_int (value), TRUE);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_constructed (GObject *object)
+{
+ GtkSourceGutter *gutter;
+
+ gutter = GTK_SOURCE_GUTTER (object);
+
+ if (gutter->priv->window_type == GTK_TEXT_WINDOW_LEFT ||
+ gutter->priv->window_type == GTK_TEXT_WINDOW_RIGHT)
+ {
+ gutter->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+ }
+ else
+ {
+ gutter->priv->orientation = GTK_ORIENTATION_VERTICAL;
}
}
@@ -356,6 +505,7 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
object_class->finalize = gtk_source_gutter_finalize;
object_class->dispose = gtk_source_gutter_dispose;
+ object_class->constructed = gtk_source_gutter_constructed;
/**
* GtkSourceGutter:view:
@@ -363,12 +513,12 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
* The #GtkSourceView of the gutter
*/
g_object_class_install_property (object_class,
- PROP_VIEW,
- g_param_spec_object ("view",
- _("View"),
- _("The gutters' GtkSourceView"),
- GTK_TYPE_SOURCE_VIEW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ PROP_VIEW,
+ g_param_spec_object ("view",
+ _("View"),
+ _("The gutters' GtkSourceView"),
+ GTK_TYPE_SOURCE_VIEW,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* GtkSourceGutter:window-type:
@@ -376,73 +526,43 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
* The text window type on which the window is placed
*/
g_object_class_install_property (object_class,
- PROP_WINDOW_TYPE,
- g_param_spec_enum ("window_type",
- _("Window Type"),
- _("The gutters text window type"),
- GTK_TYPE_TEXT_WINDOW_TYPE,
- 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ PROP_WINDOW_TYPE,
+ g_param_spec_enum ("window_type",
+ _("Window Type"),
+ _("The gutters text window type"),
+ GTK_TYPE_TEXT_WINDOW_TYPE,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_type_class_add_private (object_class, sizeof(GtkSourceGutterPrivate));
- /**
- * GtkSourceGutter::cell-activated:
- * @gutter: the #GtkSourceGutter
- * @renderer: the #GtkCellRenderer which was activated
- * @iter: the #GtkTextIter at which the cell was activated
- * @event: the #GdkEvent with which the cell was activated
- *
- * Emitted when a cell has been activated (for instance when there was
- * a button press on the cell). The signal is only emitted for cells
- * that have the #activatable property set to %TRUE.
- */
- signals [CELL_ACTIVATED] =
- g_signal_new ("cell-activated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkSourceGutterClass, cell_activated),
- NULL,
- NULL,
- _gtksourceview_marshal_VOID__OBJECT_BOXED_POINTER,
- G_TYPE_NONE,
- 3,
- GTK_TYPE_CELL_RENDERER,
- GTK_TYPE_TEXT_ITER,
- GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
- /**
- * GtkSourceGutter::query-tooltip:
- * @gutter: the #GtkSourceGutter
- * @renderer: the #GtkCellRenderer which was activated
- * @iter: the #GtkTextIter at which the cell was activated
- * @tooltip: the #GtkTooltip
- *
- * Emitted when a tooltip is requested for a specific cell. Signal
- * handlers can return %TRUE to notify the tooltip has been handled.
- */
- signals [QUERY_TOOLTIP] =
- g_signal_new ("query-tooltip",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkSourceGutterClass, query_tooltip),
- g_signal_accumulator_true_handled,
- NULL,
- _gtksourceview_marshal_BOOL__OBJECT_BOXED_OBJECT,
- G_TYPE_BOOLEAN,
- 3,
- GTK_TYPE_CELL_RENDERER,
- GTK_TYPE_TEXT_ITER,
- GTK_TYPE_TOOLTIP);
+ g_object_class_install_property (object_class,
+ PROP_XPAD,
+ g_param_spec_int ("xpad",
+ _("X Padding"),
+ _("The x-padding"),
+ -1,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_type_class_add_private (object_class, sizeof(GtkSourceGutterPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_YPAD,
+ g_param_spec_int ("ypad",
+ _("Y Padding"),
+ _("The y-padding"),
+ -1,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
}
static void
gtk_source_gutter_init (GtkSourceGutter *self)
{
self->priv = GTK_SOURCE_GUTTER_GET_PRIVATE (self);
-
- self->priv->size = -1;
}
static gint
@@ -468,12 +588,13 @@ static void
append_renderer (GtkSourceGutter *gutter,
Renderer *renderer)
{
- gutter->priv->renderers =
+ gutter->priv->renderers =
g_list_insert_sorted_with_data (gutter->priv->renderers,
- renderer,
- (GCompareDataFunc)sort_by_position,
- NULL);
- revalidate_size (gutter);
+ renderer,
+ (GCompareDataFunc)sort_by_position,
+ NULL);
+
+ update_gutter_size (gutter);
}
GtkSourceGutter *
@@ -513,35 +634,208 @@ gtk_source_gutter_get_window (GtkSourceGutter *gutter)
/**
* gtk_source_gutter_insert:
* @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
* @position: the renderers position.
*
* Inserts @renderer into @gutter at @position.
*
- * Since: 2.8
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
*/
-void
+GtkSourceGutterRenderer *
gtk_source_gutter_insert (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- gint position)
+ GType gtype,
+ gint position,
+ ...)
{
- g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+ va_list ap;
+ GtkSourceGutterRenderer *ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+ g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+ va_start (ap, position);
+ ret = gtk_source_gutter_insert_valist (gutter, gtype, position, ap);
+ va_end (ap);
- append_renderer (gutter, renderer_new (renderer, position));
+ return ret;
+}
+
+/**
+ * gtk_source_gutter_insert_valist:
+ * @gutter: a #GtkSourceGutter.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
+ * @position: the renderer position.
+ * @ap: the parameters.
+ *
+ * Create and insert a new gutter renderer in the gutter. This function is
+ * mostly useful for bindings. Applications should normally use
+ * #gtk_source_gutter_renderer_insert
+ *
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_insert_valist (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ va_list ap)
+{
+ const gchar *name;
+ GArray *parameters;
+ GObjectClass *klass;
+ GParameter *params;
+ guint num_parameters;
+ GtkSourceGutterRenderer *ret;
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+ g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+ parameters = g_array_new (FALSE, TRUE, sizeof (GParameter));
+ klass = g_type_class_ref (gtype);
+
+ num_parameters = 0;
+
+ while ((name = va_arg (ap, const gchar *)) != NULL)
+ {
+ GParameter parameter;
+ GParamSpec *spec;
+ gchar *error = NULL;
+
+ spec = g_object_class_find_property (klass, name);
+
+ if (!spec)
+ {
+ g_warning ("%s: object class `%s' has no property named `%s'",
+ G_STRFUNC,
+ g_type_name (gtype),
+ name);
+
+ break;
+ }
+
+ parameter.name = name;
+
+ G_VALUE_COLLECT_INIT (¶meter.value,
+ spec->value_type,
+ ap,
+ 0,
+ &error);
+
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRFUNC, error);
+ g_free (error);
+ g_value_unset (¶meter.value);
+
+ break;
+ }
+
+ g_array_append_val (parameters, parameter);
+ ++num_parameters;
+ }
+
+ params = (GParameter *)g_array_free (parameters, FALSE);
+
+ ret = gtk_source_gutter_insertv (gutter,
+ gtype,
+ position,
+ num_parameters,
+ params);
+
+ for (i = 0; i < num_parameters; ++i)
+ {
+ g_value_unset (¶ms[i].value);
+ }
+
+ g_free (params);
+
+ return ret;
+}
+
+/**
+ * gtk_source_gutter_insertv:
+ * @gutter: a #GtkSourceGutter.
+ * @gtype: the type of the gutter renderer (must inherit from #GtkSourceGutterRenderer).
+ * @position: the renderer position.
+ * @num_parameters: the number of parameters.
+ * @parameters: the parameters.
+ *
+ * Create and insert a new gutter renderer in the gutter. This function is
+ * mostly useful for bindings. Applications should normally use
+ * #gtk_source_gutter_renderer_insert
+ *
+ * Since: 3.0
+ *
+ * Returns: (transfer none): a #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_insertv (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ guint num_parameters,
+ GParameter *parameters)
+{
+ GParameter *extended;
+ guint i;
+ gint len;
+ GValue *view;
+ GValue *window_type;
+ Renderer *renderer;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER (gutter), NULL);
+ g_return_val_if_fail (g_type_is_a (gtype, GTK_TYPE_SOURCE_GUTTER_RENDERER), NULL);
+
+ len = sizeof (GParameter) * (num_parameters + 2);
+ extended = g_slice_alloc0 (len);
+
+ for (i = 0; i < num_parameters; ++i)
+ {
+ extended[i] = parameters[i];
+ }
+
+ extended[num_parameters].name = "view";
+ view = &(extended[num_parameters].value);
+ g_value_init (view, GTK_TYPE_TEXT_VIEW);
+ g_value_set_object (view, gutter->priv->view);
+
+ extended[num_parameters + 1].name = "window-type";
+ window_type = &(extended[num_parameters + 1].value);
+ g_value_init (window_type, GTK_TYPE_TEXT_WINDOW_TYPE);
+ g_value_set_enum (window_type, gutter->priv->window_type);
+
+ renderer = renderer_new (gutter,
+ gtype,
+ position,
+ num_parameters + 2,
+ extended);
+
+ append_renderer (gutter, renderer);
+
+ g_value_unset (view);
+ g_value_unset (window_type);
+
+ g_slice_free1 (len, extended);
+
+ return renderer->renderer;
}
static gboolean
-renderer_find (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- Renderer **ret,
- GList **retlist)
+renderer_find (GtkSourceGutter *gutter,
+ GtkSourceGutterRenderer *renderer,
+ Renderer **ret,
+ GList **retlist)
{
GList *list;
for (list = gutter->priv->renderers; list; list = g_list_next (list))
{
- *ret = (Renderer *)list->data;
+ *ret = list->data;
if ((*ret)->renderer == renderer)
{
@@ -557,10 +851,9 @@ renderer_find (GtkSourceGutter *gutter,
return FALSE;
}
-
/**
* gtk_source_gutter_reorder:
- * @gutter: a #GtkSourceGutter.
+ * @gutter: a #GtkSourceGutterRenderer.
* @renderer: a #GtkCellRenderer.
* @position: the new renderer position.
*
@@ -569,19 +862,22 @@ renderer_find (GtkSourceGutter *gutter,
* Since: 2.8
*/
void
-gtk_source_gutter_reorder (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- gint position)
+gtk_source_gutter_reorder (GtkSourceGutter *gutter,
+ GtkSourceGutterRenderer *renderer,
+ gint position)
{
Renderer *ret;
GList *retlist;
g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
if (renderer_find (gutter, renderer, &ret, &retlist))
{
- gutter->priv->renderers = g_list_remove_link (gutter->priv->renderers, retlist);
+ gutter->priv->renderers =
+ g_list_remove_link (gutter->priv->renderers,
+ retlist);
+
ret->position = position;
append_renderer (gutter, ret);
}
@@ -590,114 +886,33 @@ gtk_source_gutter_reorder (GtkSourceGutter *gutter,
/**
* gtk_source_gutter_remove:
* @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
+ * @renderer: a #GtkSourceGutterRenderer.
*
* Removes @renderer from @gutter.
*
* Since: 2.8
*/
void
-gtk_source_gutter_remove (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer)
+gtk_source_gutter_remove (GtkSourceGutter *gutter,
+ GtkSourceGutterRenderer *renderer)
{
Renderer *ret;
GList *retlist;
g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
if (renderer_find (gutter, renderer, &ret, &retlist))
{
- gutter->priv->renderers = g_list_remove_link (gutter->priv->renderers, retlist);
+ gutter->priv->renderers =
+ g_list_remove_link (gutter->priv->renderers,
+ retlist);
- revalidate_size (gutter);
- renderer_free (ret);
- }
-}
+ g_object_set (ret->renderer, "view", NULL, NULL);
-/**
- * gtk_source_gutter_set_cell_data_func:
- * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
- * @func: (allow-none): the #GtkSourceGutterDataFunc to use.
- * @func_data: (allow-none): the user data for @func.
- * @destroy: (allow-none): the destroy notification for @func_data.
- *
- * Sets the #GtkSourceGutterDataFunc to use for @renderer. This function is
- * used to setup the cell renderer properties for rendering the current cell.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_set_cell_data_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceGutterDataFunc func,
- gpointer func_data,
- GDestroyNotify destroy)
-{
- Renderer *ret;
-
- g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
- if (!renderer_find (gutter, renderer, &ret, NULL))
- {
- return;
- }
-
- if (ret->data_func_data && ret->data_func_destroy)
- {
- ret->data_func_destroy (ret->data_func_data);
- }
-
- ret->data_func = func;
- ret->data_func_data = func_data;
- ret->data_func_destroy = destroy;
-
- revalidate_size (gutter);
-}
-
-/**
- * gtk_source_gutter_set_cell_size_func:
- * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkCellRenderer.
- * @func: (allow-none): the #GtkSourceGutterSizeFunc to use.
- * @func_data: (allow-none): the user data for @func.
- * @destroy: (allow-none): the destroy notification for @func_data.
- *
- * Sets the #GtkSourceGutterSizeFunc to use for @renderer. This function is
- * used to setup the cell renderer properties for measuring the maximum size
- * of the cell.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_set_cell_size_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceGutterSizeFunc func,
- gpointer func_data,
- GDestroyNotify destroy)
-{
- Renderer *ret;
-
- g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
- if (!renderer_find (gutter, renderer, &ret, NULL))
- {
- return;
- }
-
- if (ret->size_func_data && ret->size_func_destroy)
- {
- ret->size_func_destroy (ret->size_func_data);
+ update_gutter_size (gutter);
+ renderer_free (ret);
}
-
- ret->size_func = func;
- ret->size_func_data = func_data;
- ret->size_func_destroy = destroy;
-
- revalidate_size (gutter);
}
/**
@@ -714,72 +929,33 @@ gtk_source_gutter_queue_draw (GtkSourceGutter *gutter)
{
g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- revalidate_size (gutter);
-}
-
-static gint
-calculate_size (GtkSourceGutter *gutter,
- Renderer *renderer)
-{
- gint width = -1;
-
- gtk_cell_renderer_get_fixed_size (renderer->renderer, &width, NULL);
-
- if (width == -1 && renderer->size_func)
- {
- GtkRequisition req;
- renderer->size_func (gutter, renderer->renderer, renderer->size_func_data);
-
- gtk_cell_renderer_get_preferred_size (renderer->renderer,
- GTK_WIDGET (gutter->priv->view),
- &req, NULL);
- width = req.width;
- }
-
- return width == -1 ? 1 : width;
-}
-
-static gint
-calculate_sizes (GtkSourceGutter *gutter,
- GArray *sizes)
-{
- GList *item;
- gint total_width = 0;
-
- /* Calculate size */
- for (item = gutter->priv->renderers; item; item = g_list_next (item))
- {
- Renderer *renderer = (Renderer *)item->data;
- gint width;
-
- width = calculate_size (gutter, renderer);
- g_array_append_val (sizes, width);
-
- total_width += width;
- }
-
- return total_width;
+ do_redraw (gutter);
}
/* This function is taken from gtk+/tests/testtext.c */
-static void
+static gint
get_lines (GtkTextView *text_view,
gint first_y,
gint last_y,
GArray *buffer_coords,
GArray *line_heights,
GArray *numbers,
- gint *countp)
+ gint *countp,
+ GtkTextIter *start,
+ GtkTextIter *end)
{
GtkTextIter iter;
gint count;
gint last_line_num = -1;
+ gint total_height = 0;
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);
@@ -788,6 +964,8 @@ get_lines (GtkTextView *text_view,
* Stop when we pass last_y */
count = 0;
+ *start = iter;
+
while (!gtk_text_iter_is_end (&iter))
{
gint y, height;
@@ -801,13 +979,17 @@ get_lines (GtkTextView *text_view,
g_array_append_val (line_heights, height);
}
+ total_height += height;
+
last_line_num = gtk_text_iter_get_line (&iter);
g_array_append_val (numbers, last_line_num);
++count;
if ((y + height) >= last_y)
+ {
break;
+ }
gtk_text_iter_forward_line (&iter);
}
@@ -830,6 +1012,8 @@ get_lines (GtkTextView *text_view,
g_array_append_val (line_heights, height);
}
+ total_height += height;
+
g_array_append_val (numbers, line_num);
++count;
}
@@ -852,8 +1036,14 @@ get_lines (GtkTextView *text_view,
{
gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
g_array_append_val (line_heights, height);
+
+ total_height += height;
}
}
+
+ *end = iter;
+
+ return total_height;
}
static gboolean
@@ -864,8 +1054,27 @@ on_view_draw (GtkSourceView *view,
GdkWindow *window;
GtkTextView *text_view;
GArray *sizes;
- GdkRectangle clip;
+ GdkRectangle clip;
gint size;
+ gint x, y;
+ gint y1, y2;
+ GArray *numbers;
+ GArray *pixels;
+ GArray *heights;
+ GtkTextIter cur;
+ gint cur_line;
+ gint count;
+ gint i;
+ GList *item;
+ GtkTextIter start;
+ GtkTextIter end;
+ GtkTextBuffer *buffer;
+ GdkRectangle background_area;
+ GdkRectangle cell_area;
+ GtkTextIter selection_start;
+ GtkTextIter selection_end;
+ gboolean has_selection;
+ gint idx;
window = gtk_source_gutter_get_window (gutter);
@@ -874,195 +1083,261 @@ on_view_draw (GtkSourceView *view,
return FALSE;
}
- gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
+ gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
text_view = GTK_TEXT_VIEW (view);
+
+ if (!gdk_cairo_get_clip_rectangle (cr, &clip))
+ {
+ return FALSE;
+ }
+
+ gutter->priv->is_drawing = TRUE;
+
+ buffer = gtk_text_view_get_buffer (text_view);
+
+ gdk_window_get_pointer (window, &x, &y, NULL);
+
+ y1 = clip.y;
+ y2 = y1 + clip.height;
+
+ /* get the extents of the line printing */
+ gtk_text_view_window_to_buffer_coords (text_view,
+ gutter->priv->window_type,
+ 0,
+ y1,
+ NULL,
+ &y1);
+
+ gtk_text_view_window_to_buffer_coords (text_view,
+ gutter->priv->window_type,
+ 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));
sizes = g_array_new (FALSE, FALSE, sizeof (gint));
- /* This is fairly ugly, but we could not find a better way to
- * do it: renderers could have changed size and they do not have
- * a way to signal it. So on draw we revalidate the size and
- * requeue another draw.
- * To see if the size has changed we test the size of only the
- * gutter itself since the full border window size is not under
- * our control (see e.g bug #589382).
- * This also means that if the user manually forces the
- * border_window_size to a value smaller than the gutter, things
- * will not be drawn properly. */
- size = calculate_sizes (gutter, sizes);
- if (gutter->priv->size != size)
+ size = calculate_gutter_size (gutter, sizes);
+
+ i = 0;
+ x = 0;
+
+ background_area.x = 0;
+ background_area.height = get_lines (text_view,
+ y1,
+ y2,
+ pixels,
+ heights,
+ numbers,
+ &count,
+ &start,
+ &end);
+
+ cell_area.x = gutter->priv->xpad;
+ cell_area.height = background_area.height;
+
+ gtk_text_view_buffer_to_window_coords (text_view,
+ gutter->priv->window_type,
+ 0,
+ g_array_index (pixels, gint, 0),
+ NULL,
+ &background_area.y);
+
+ cell_area.y = background_area.y;
+
+ item = gutter->priv->renderers;
+ idx = 0;
+
+ while (item)
{
- gint border_size;
+ Renderer *renderer = item->data;
+ gint xpad;
+ gint width;
- border_size = gtk_text_view_get_border_window_size (text_view, gutter->priv->window_type);
+ width = g_array_index (sizes, gint, idx++);
- if (gutter->priv->size < 0)
- border_size += size;
- else
- border_size = MAX (0, border_size - gutter->priv->size) + size;
+ if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
+ {
+ gtk_source_gutter_renderer_get_padding (renderer->renderer,
+ &xpad,
+ NULL);
+
+ background_area.width = width;
+
+ cell_area.width = width - 2 * xpad;
+ cell_area.x = background_area.x + xpad;
+
+ cairo_save (cr);
+
+ gdk_cairo_rectangle (cr, &background_area);
+ cairo_clip (cr);
+
+ gtk_source_gutter_renderer_begin (renderer->renderer,
+ cr,
+ &background_area,
+ &cell_area,
+ &start,
+ &end);
+
+ cairo_restore (cr);
+
+ background_area.x += background_area.width;
+ }
+
+ item = g_list_next (item);
+ }
+
+ gtk_text_buffer_get_iter_at_mark (buffer,
+ &cur,
+ gtk_text_buffer_get_insert (buffer));
+
+ cur_line = gtk_text_iter_get_line (&cur);
- gutter->priv->size = size;
+ gtk_text_buffer_get_selection_bounds (buffer,
+ &selection_start,
+ &selection_end);
- /* Will trigger a new draw */
- gtk_text_view_set_border_window_size (text_view, gutter->priv->window_type, border_size);
+ has_selection = !gtk_text_iter_equal (&selection_start, &selection_end);
+
+ if (has_selection)
+ {
+ if (!gtk_text_iter_starts_line (&selection_start))
+ {
+ gtk_text_iter_set_line_offset (&selection_start, 0);
+ }
+
+ if (!gtk_text_iter_ends_line (&selection_end))
+ {
+ gtk_text_iter_forward_to_line_end (&selection_end);
+ }
}
- else if (gdk_cairo_get_clip_rectangle (cr, &clip))
+
+ for (i = 0; i < count; ++i)
{
- GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
- gint x, y;
- gint y1, y2;
- GArray *numbers;
- GArray *pixels;
- GArray *heights;
- GtkTextIter cur;
- gint cur_line;
- gint count;
- gint i;
- GList *item;
-
- gdk_window_get_pointer (window, &x, &y, NULL);
-
- y1 = clip.y;
- y2 = y1 + clip.height;
-
- /* get the extents of the line printing */
- gtk_text_view_window_to_buffer_coords (text_view,
- gutter->priv->window_type,
- 0,
- y1,
- NULL,
- &y1);
-
- gtk_text_view_window_to_buffer_coords (text_view,
- gutter->priv->window_type,
- 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. */
- get_lines (text_view, y1, y2, pixels, heights, numbers, &count);
-
- gtk_text_buffer_get_iter_at_mark (buffer,
- &cur,
- gtk_text_buffer_get_insert (buffer));
-
- cur_line = gtk_text_iter_get_line (&cur);
-
- for (i = 0; i < count; ++i)
+ gint pos;
+ gint line_to_paint;
+
+ end = start;
+
+ if (!gtk_text_iter_ends_line (&end))
{
- gint pos;
- gint line_to_paint;
- GdkRectangle cell_area;
- gint idx = 0;
+ gtk_text_iter_forward_to_line_end (&end);
+ }
+
+ gtk_text_view_buffer_to_window_coords (text_view,
+ gutter->priv->window_type,
+ 0,
+ g_array_index (pixels, gint, i),
+ NULL,
+ &pos);
- gtk_text_view_buffer_to_window_coords (text_view,
- gutter->priv->window_type,
- 0,
- g_array_index (pixels, gint, i),
- NULL,
- &pos);
+ line_to_paint = g_array_index (numbers, gint, i);
- line_to_paint = g_array_index (numbers, gint, i);
+ background_area.y = pos;
+ background_area.height = g_array_index (heights, gint, i);
+ background_area.x = 0;
- cell_area.x = 0;
- cell_area.y = pos;
- cell_area.height = g_array_index (heights, gint, i);
+ idx = 0;
+
+ for (item = gutter->priv->renderers; item; item = g_list_next (item))
+ {
+ Renderer *renderer;
+ gint width;
+ GtkSourceGutterRendererState state;
+ gint xpad;
+ gint ypad;
- for (item = gutter->priv->renderers; item; item = g_list_next (item))
+ renderer = item->data;
+ width = g_array_index (sizes, gint, idx++);
+
+ if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
{
- Renderer *renderer = (Renderer *)item->data;
- gint width = g_array_index (sizes, gint, idx++);
- GtkCellRendererState state = 0;
-
- cell_area.width = width;
-
- /* Call data func if needed */
- if (renderer->data_func)
- {
- renderer->data_func (gutter,
- renderer->renderer,
- line_to_paint,
- line_to_paint == cur_line,
- renderer->data_func_data);
- }
-
- if (x >= cell_area.x && x < cell_area.x + cell_area.width &&
- y >= cell_area.y && y < cell_area.y + cell_area.height)
- {
- GtkCellRendererMode mode;
-
- g_object_get (G_OBJECT (renderer->renderer),
- "mode", &mode,
- NULL);
-
- if (mode & GTK_CELL_RENDERER_MODE_ACTIVATABLE)
- state = GTK_CELL_RENDERER_PRELIT;
- }
-
- /* Call render with correct area */
- gtk_cell_renderer_render (renderer->renderer,
- cr,
- GTK_WIDGET (view),
- &cell_area,
- &cell_area,
- state);
-
- cell_area.x += cell_area.width;
+ continue;
}
- }
- g_array_free (numbers, TRUE);
- g_array_free (pixels, TRUE);
- g_array_free (heights, TRUE);
- }
+ gtk_source_gutter_renderer_get_padding (renderer->renderer,
+ &xpad,
+ &ypad);
- g_array_free (sizes, TRUE);
+ background_area.width = width;
- return FALSE;
-}
+ cell_area.y = background_area.y + ypad;
+ cell_area.height = background_area.height - 2 * ypad;
-static gboolean
-redraw_for_window (GtkSourceGutter *gutter,
- GdkEventAny *event,
- gboolean act_on_window)
-{
- if (event->window == gtk_source_gutter_get_window (gutter) || !act_on_window)
- {
- gtk_source_gutter_queue_draw (gutter);
+ cell_area.x = background_area.x + xpad;
+ cell_area.width = background_area.width - 2 * xpad;
+
+ state = GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL;
+
+ if (line_to_paint == cur_line)
+ {
+ state |= GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR;
+ }
+
+ if (has_selection &&
+ gtk_text_iter_in_range (&start,
+ &selection_start,
+ &selection_end))
+ {
+ state |= GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED;
+ }
+
+ if (renderer->prelit >= 0 && cell_area.y <= renderer->prelit && cell_area.y + cell_area.height >= renderer->prelit)
+ {
+ state |= GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
+ }
+
+ gtk_source_gutter_renderer_query_data (renderer->renderer,
+ &start,
+ &end,
+ state);
+
+ cairo_save (cr);
+
+ gdk_cairo_rectangle (cr, &background_area);
+
+ cairo_clip (cr);
+
+ /* Call render with correct area */
+ gtk_source_gutter_renderer_draw (renderer->renderer,
+ cr,
+ &background_area,
+ &cell_area,
+ &start,
+ &end,
+ state);
+
+ cairo_restore (cr);
+
+ background_area.x += background_area.width;
+ }
+
+ gtk_text_iter_forward_line (&start);
}
- return FALSE;
-}
+ for (item = gutter->priv->renderers; item; item = g_list_next (item))
+ {
+ Renderer *renderer = item->data;
-static gboolean
-on_view_motion_notify_event (GtkSourceView *view,
- GdkEventMotion *event,
- GtkSourceGutter *gutter)
-{
- return redraw_for_window (gutter, (GdkEventAny *)event, TRUE);
-}
+ if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
+ {
+ gtk_source_gutter_renderer_end (renderer->renderer);
+ }
+ }
+ g_array_free (numbers, TRUE);
+ g_array_free (pixels, TRUE);
+ g_array_free (heights, TRUE);
-static gboolean
-on_view_enter_notify_event (GtkSourceView *view,
- GdkEventCrossing *event,
- GtkSourceGutter *gutter)
-{
- return redraw_for_window (gutter, (GdkEventAny *)event, TRUE);
-}
+ g_array_free (sizes, TRUE);
+ gutter->priv->is_drawing = FALSE;
-static gboolean
-on_view_leave_notify_event (GtkSourceView *view,
- GdkEventCrossing *event,
- GtkSourceGutter *gutter)
-{
- return redraw_for_window (gutter, (GdkEventAny *)event, FALSE);
+ return FALSE;
}
static Renderer *
@@ -1072,61 +1347,113 @@ renderer_at_x (GtkSourceGutter *gutter,
gint *width)
{
GList *item;
+ gint s;
+ gint w;
+
+ update_gutter_size (gutter);
+
+ s = 0;
for (item = gutter->priv->renderers; item; item = g_list_next (item))
{
- Renderer *renderer = (Renderer *)item->data;
+ Renderer *renderer = item->data;
+ gint xpad;
+
+ w = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+ gtk_source_gutter_renderer_get_padding (renderer->renderer,
+ &xpad,
+ NULL);
- *width = calculate_size (gutter, renderer);
+ s += xpad;
- if (x >= *start && x < *start + *width)
+ if (w > 0 && x >= s && x < s + w)
{
+ if (width)
+ {
+ *width = w;
+ }
+
+ if (start)
+ {
+ *start = s;
+ }
+
return renderer;
}
- *start += *width;
+ s += w + xpad;
}
return NULL;
}
-static gboolean
-on_view_button_press_event (GtkSourceView *view,
- GdkEventButton *event,
- GtkSourceGutter *gutter)
+static void
+get_renderer_rect (GtkSourceGutter *gutter,
+ Renderer *renderer,
+ GtkTextIter *iter,
+ gint line,
+ GdkRectangle *rectangle,
+ gint start)
{
- Renderer *renderer;
- gint yline;
- GtkTextIter line_iter;
- GtkTextIter cur;
- gint cur_line;
- gint line;
- gint y_buf;
- gint start = 0;
- gint width = 0;
- GtkTextBuffer *buffer;
- GtkCellRendererMode mode;
+ GList *item;
+ gint y;
+ gint ypad;
- if (event->window != gtk_source_gutter_get_window (gutter))
- {
- return FALSE;
- }
+ item = gutter->priv->renderers;
+ rectangle->x = start;
- /* Check cell renderer */
- renderer = renderer_at_x (gutter, event->x, &start, &width);
+ gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (gutter->priv->view),
+ iter,
+ &y,
+ &rectangle->height);
+
+ rectangle->width = gtk_source_gutter_renderer_get_size (renderer->renderer);
+
+ gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (gutter->priv->view),
+ gutter->priv->window_type,
+ 0,
+ y,
+ NULL,
+ &rectangle->y);
+
+ gtk_source_gutter_renderer_get_padding (renderer->renderer,
+ NULL,
+ &ypad);
+
+ rectangle->y += ypad;
+ rectangle->height -= 2 * ypad;
+}
+
+static gboolean
+renderer_query_activatable (GtkSourceGutter *gutter,
+ Renderer *renderer,
+ GdkEvent *event,
+ gint x,
+ gint y,
+ GtkTextIter *line_iter,
+ GdkRectangle *rect,
+ gint start)
+{
+ gint y_buf;
+ gint yline;
+ GtkTextIter iter;
+ GdkRectangle r;
if (!renderer)
{
return FALSE;
}
- gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (gutter->priv->view),
gutter->priv->window_type,
- event->x, event->y,
- NULL, &y_buf);
+ x,
+ y,
+ NULL,
+ &y_buf);
- gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (view),
- &line_iter,
+ gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (gutter->priv->view),
+ &iter,
y_buf,
&yline);
@@ -1135,73 +1462,172 @@ on_view_button_press_event (GtkSourceView *view,
return FALSE;
}
- line = gtk_text_iter_get_line (&line_iter);
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ get_renderer_rect (gutter, renderer, &iter, yline, &r, start);
- gtk_text_buffer_get_iter_at_mark (buffer,
- &cur,
- gtk_text_buffer_get_insert (buffer));
+ if (line_iter)
+ {
+ *line_iter = iter;
+ }
- cur_line = gtk_text_iter_get_line (&cur);
+ if (rect)
+ {
+ *rect = r;
+ }
+
+ if (y < r.y || y > r.y + r.height)
+ {
+ return FALSE;
+ }
+
+ return gtk_source_gutter_renderer_query_activatable (renderer->renderer,
+ &iter,
+ &r,
+ event);
+}
+
+static gboolean
+redraw_for_window (GtkSourceGutter *gutter,
+ GdkEventAny *event,
+ gboolean act_on_window,
+ gint x,
+ gint y)
+{
+ Renderer *at_x = NULL;
+ GList *item;
+ gboolean redraw;
+ gint start;
+
+ if (event->window != gtk_source_gutter_get_window (gutter) && act_on_window)
+ {
+ return FALSE;
+ }
- if (renderer->data_func)
+ if (act_on_window)
{
- renderer->data_func (gutter,
- renderer->renderer,
- line,
- line == cur_line,
- renderer->data_func_data);
+ at_x = renderer_at_x (gutter, x, &start, NULL);
}
- g_object_get (G_OBJECT (renderer->renderer),
- "mode", &mode,
- NULL);
+ redraw = FALSE;
- if (mode & GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+ for (item = gutter->priv->renderers; item; item = g_list_next (item))
{
- GdkRectangle area;
- gchar *path;
- gboolean ret;
-
- gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (view),
- &line_iter,
- &area.y,
- &area.height);
- area.x = start;
- area.width = width;
-
- path = g_strdup_printf ("%d", line);
-
- ret = gtk_cell_renderer_activate (renderer->renderer,
- (GdkEvent *)event,
- GTK_WIDGET (gutter->priv->view),
- path,
- &area,
- &area,
- 0);
-
- g_signal_emit (gutter,
- signals[CELL_ACTIVATED],
- 0,
- renderer->renderer,
- &line_iter,
- (GdkEvent *)event);
-
- g_free (path);
+ Renderer *renderer = item->data;
+ gint prelit = renderer->prelit;
+
+ if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
+ {
+ renderer->prelit = -1;
+ }
+ else
+ {
+ if (renderer != at_x || !act_on_window)
+ {
+ renderer->prelit = -1;
+ }
+ else if (renderer_query_activatable (gutter,
+ renderer,
+ (GdkEvent *)event,
+ x,
+ y,
+ NULL,
+ NULL,
+ start))
+ {
+ renderer->prelit = y;
+ }
+ else
+ {
+ renderer->prelit = -1;
+ }
+ }
+
+ redraw |= (renderer->prelit != prelit);
+ }
+
+ if (redraw)
+ {
+ do_redraw (gutter);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+on_view_motion_notify_event (GtkSourceView *view,
+ GdkEventMotion *event,
+ GtkSourceGutter *gutter)
+{
+ return redraw_for_window (gutter,
+ (GdkEventAny *)event,
+ TRUE,
+ (gint)event->x,
+ (gint)event->y);
+}
+
+static gboolean
+on_view_enter_notify_event (GtkSourceView *view,
+ GdkEventCrossing *event,
+ GtkSourceGutter *gutter)
+{
+ return redraw_for_window (gutter,
+ (GdkEventAny *)event,
+ TRUE,
+ (gint)event->x,
+ (gint)event->y);
+}
+
+static gboolean
+on_view_leave_notify_event (GtkSourceView *view,
+ GdkEventCrossing *event,
+ GtkSourceGutter *gutter)
+{
+ return redraw_for_window (gutter,
+ (GdkEventAny *)event,
+ FALSE,
+ (gint)event->x,
+ (gint)event->y);
+}
+
+static gboolean
+on_view_button_press_event (GtkSourceView *view,
+ GdkEventButton *event,
+ GtkSourceGutter *gutter)
+{
+ Renderer *renderer;
+ GtkTextIter line_iter;
+ gint start = -1;
+ GdkRectangle rect;
+
+ if (event->window != gtk_source_gutter_get_window (gutter))
+ {
+ return FALSE;
+ }
+
+ if (event->type != GDK_BUTTON_PRESS)
+ {
+ return FALSE;
+ }
+
+ /* Check cell renderer */
+ renderer = renderer_at_x (gutter, event->x, &start, NULL);
+
+ if (renderer_query_activatable (gutter,
+ renderer,
+ (GdkEvent *)event,
+ (gint)event->x,
+ (gint)event->y,
+ &line_iter,
+ &rect,
+ start))
+ {
+ gtk_source_gutter_renderer_activate (renderer->renderer,
+ &line_iter,
+ &rect,
+ (GdkEvent *)event);
+
do_redraw (gutter);
- /* WARNING, DANGER, DANGER:
- * FIXME: this is really just a hack because we lack a return
- * value in the CELL_ACTIVATED signal, so handlers of cell
- * activating have no way to consume the button event. A left
- * click in the gutter will by default remove the selection
- * in the textview, which is bad because we implement some
- * selection stuff in GtkSourceView when clicking on the line
- * renderer. Anyway, for 3.0 we should change the
- * cell-activated signal to allow a return value and remove
- * this hack
- */
- return ret || event->button == 1;
+ return TRUE;
}
return FALSE;
@@ -1222,7 +1648,7 @@ on_view_query_tooltip (GtkSourceView *view,
gint y_buf;
gint yline;
GtkTextIter line_iter;
- gboolean ret;
+ GdkRectangle rect;
if (keyboard_mode)
{
@@ -1252,15 +1678,48 @@ on_view_query_tooltip (GtkSourceView *view,
return FALSE;
}
- g_signal_emit (gutter,
- signals[QUERY_TOOLTIP],
- 0,
- renderer->renderer,
- &line_iter,
- tooltip,
- &ret);
+ get_renderer_rect (gutter,
+ renderer,
+ &line_iter,
+ yline,
+ &rect,
+ start);
+
+ return gtk_source_gutter_renderer_query_tooltip (renderer->renderer,
+ &line_iter,
+ &rect,
+ x,
+ y,
+ tooltip);
+}
+
+void
+gtk_source_gutter_set_padding (GtkSourceGutter *gutter,
+ gint xpad,
+ gint ypad)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
- return ret;
+ if (set_xpad (gutter, xpad, FALSE) || set_ypad (gutter, ypad, FALSE))
+ {
+ update_gutter_size (gutter);
+ }
}
-/* vi:ts=8 */
+void
+gtk_source_gutter_get_padding (GtkSourceGutter *gutter,
+ gint *xpad,
+ gint *ypad)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER (gutter));
+
+ if (xpad)
+ {
+ *xpad = gutter->priv->xpad;
+ }
+
+ if (ypad)
+ {
+ *ypad = gutter->priv->ypad;
+ }
+}
diff --git a/gtksourceview/gtksourcegutter.h b/gtksourceview/gtksourcegutter.h
index 4dda080..0b4beec 100644
--- a/gtksourceview/gtksourcegutter.h
+++ b/gtksourceview/gtksourcegutter.h
@@ -26,6 +26,7 @@
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
+#include <gtksourceview/gtksourcegutterrenderer.h>
G_BEGIN_DECLS
@@ -40,64 +41,57 @@ typedef struct _GtkSourceGutter GtkSourceGutter;
typedef struct _GtkSourceGutterClass GtkSourceGutterClass;
typedef struct _GtkSourceGutterPrivate GtkSourceGutterPrivate;
-struct _GtkSourceGutter {
+struct _GtkSourceGutter
+{
GObject parent;
GtkSourceGutterPrivate *priv;
};
-struct _GtkSourceGutterClass {
+struct _GtkSourceGutterClass
+{
GObjectClass parent_class;
-
- void (*cell_activated) (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkTextIter *iter,
- GdkEvent *event);
-
- gboolean (*query_tooltip) (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkTextIter *iter,
- GtkTooltip *tooltip);
};
-typedef void (*GtkSourceGutterDataFunc) (GtkSourceGutter *gutter,
- GtkCellRenderer *cell,
- gint line_number,
- gboolean current_line,
- gpointer data);
-
-typedef void (*GtkSourceGutterSizeFunc) (GtkSourceGutter *gutter,
- GtkCellRenderer *cell,
- gpointer data);
-
GType gtk_source_gutter_get_type (void) G_GNUC_CONST;
GdkWindow *gtk_source_gutter_get_window (GtkSourceGutter *gutter);
-void gtk_source_gutter_insert (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- gint position);
+GtkSourceGutterRenderer *
+ gtk_source_gutter_insert (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ ...) G_GNUC_NULL_TERMINATED;
+
+GtkSourceGutterRenderer *
+ gtk_source_gutter_insert_valist (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ va_list ap);
+
+GtkSourceGutterRenderer *
+ gtk_source_gutter_insertv (GtkSourceGutter *gutter,
+ GType gtype,
+ gint position,
+ guint num_parameters,
+ GParameter *parameters);
void gtk_source_gutter_reorder (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
+ GtkSourceGutterRenderer *renderer,
gint position);
void gtk_source_gutter_remove (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer);
+ GtkSourceGutterRenderer *renderer);
-void gtk_source_gutter_set_cell_data_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceGutterDataFunc func,
- gpointer func_data,
- GDestroyNotify destroy);
+void gtk_source_gutter_queue_draw (GtkSourceGutter *gutter);
-void gtk_source_gutter_set_cell_size_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceGutterSizeFunc func,
- gpointer func_data,
- GDestroyNotify destroy);
+void gtk_source_gutter_set_padding (GtkSourceGutter *gutter,
+ gint xpad,
+ gint ypad);
-void gtk_source_gutter_queue_draw (GtkSourceGutter *gutter);
+void gtk_source_gutter_get_padding (GtkSourceGutter *gutter,
+ gint *xpad,
+ gint *ypad);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutterrenderer.c b/gtksourceview/gtksourcegutterrenderer.c
new file mode 100644
index 0000000..fd8fbff
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderer.c
@@ -0,0 +1,1227 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderer.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtksourcegutterrenderer.h"
+#include "gtksourceview-marshal.h"
+#include "gtksourceview-typebuiltins.h"
+#include "gtksourceview-i18n.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererPrivate))
+
+enum
+{
+ ACTIVATE,
+ SIZE_CHANGED,
+ QUEUE_DRAW,
+ QUERY_TOOLTIP,
+ QUERY_DATA,
+ QUERY_ACTIVATABLE,
+ NUM_SIGNALS
+};
+
+struct _GtkSourceGutterRendererPrivate
+{
+ GtkTextView *view;
+ GtkTextWindowType window_type;
+
+ gint xpad;
+ gint ypad;
+
+ gfloat xalign;
+ gfloat yalign;
+
+ gint size;
+
+ GdkColor background_gdk;
+ gboolean background_set;
+
+ GtkSourceGutterRendererAlignmentMode alignment_mode;
+
+ guint visible : 1;
+};
+
+static guint signals[NUM_SIGNALS] = {0,};
+
+G_DEFINE_ABSTRACT_TYPE (GtkSourceGutterRenderer,
+ gtk_source_gutter_renderer,
+ G_TYPE_INITIALLY_UNOWNED)
+
+enum
+{
+ PROP_0,
+ PROP_VISIBLE,
+ PROP_XPAD,
+ PROP_YPAD,
+ PROP_XALIGN,
+ PROP_YALIGN,
+ PROP_VIEW,
+ PROP_ALIGNMENT_MODE,
+ PROP_WINDOW_TYPE,
+ PROP_SIZE,
+ PROP_BACKGROUND_GDK,
+ PROP_BACKGROUND_SET
+};
+
+static void
+gtk_source_gutter_renderer_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_parent_class)->finalize (object);
+}
+
+static gboolean
+set_visible (GtkSourceGutterRenderer *renderer,
+ gboolean visible)
+{
+ if (renderer->priv->visible == visible)
+ {
+ return FALSE;
+ }
+
+ renderer->priv->visible = visible;
+ g_object_notify (G_OBJECT (renderer), "visible");
+
+ gtk_source_gutter_renderer_queue_draw (renderer);
+
+ return TRUE;
+}
+
+
+static gboolean
+set_padding (GtkSourceGutterRenderer *renderer,
+ gint *field,
+ gint padding,
+ const gchar *name)
+{
+ if (*field == padding || padding < 0)
+ {
+ return FALSE;
+ }
+
+ *field = padding;
+ g_object_notify (G_OBJECT (renderer), name);
+
+ return TRUE;
+}
+
+static gboolean
+set_xpad (GtkSourceGutterRenderer *renderer,
+ gint xpad)
+{
+ return set_padding (renderer,
+ &renderer->priv->xpad,
+ xpad,
+ "xpad");
+}
+
+static gboolean
+set_ypad (GtkSourceGutterRenderer *renderer,
+ gint ypad)
+{
+ return set_padding (renderer,
+ &renderer->priv->ypad,
+ ypad,
+ "ypad");
+}
+
+static gboolean
+set_alignment (GtkSourceGutterRenderer *renderer,
+ gfloat *field,
+ gfloat align,
+ const gchar *name,
+ gboolean emit)
+{
+ if (*field == align || align < 0)
+ {
+ return FALSE;
+ }
+
+ *field = align;
+ g_object_notify (G_OBJECT (renderer), name);
+
+ if (emit)
+ {
+ gtk_source_gutter_renderer_queue_draw (renderer);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+set_xalign (GtkSourceGutterRenderer *renderer,
+ gfloat xalign,
+ gboolean emit)
+{
+ return set_alignment (renderer,
+ &renderer->priv->xalign,
+ xalign,
+ "xalign",
+ emit);
+}
+
+static gboolean
+set_yalign (GtkSourceGutterRenderer *renderer,
+ gfloat yalign,
+ gboolean emit)
+{
+ return set_alignment (renderer,
+ &renderer->priv->yalign,
+ yalign,
+ "yalign",
+ emit);
+}
+
+static void
+set_alignment_mode (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterRendererAlignmentMode mode)
+{
+ if (renderer->priv->alignment_mode == mode)
+ {
+ return;
+ }
+
+ renderer->priv->alignment_mode = mode;
+ g_object_notify (G_OBJECT (renderer), "alignment-mode");
+
+ gtk_source_gutter_renderer_queue_draw (renderer);
+}
+
+static void
+set_size (GtkSourceGutterRenderer *renderer,
+ gint value)
+{
+ if (renderer->priv->size == value)
+ {
+ return;
+ }
+
+ renderer->priv->size = value;
+ g_object_notify (G_OBJECT (renderer), "size");
+}
+
+static void
+set_background_gdk_set (GtkSourceGutterRenderer *renderer,
+ gboolean isset)
+{
+ if (isset == renderer->priv->background_set)
+ {
+ return;
+ }
+
+ renderer->priv->background_set = isset;
+ gtk_source_gutter_renderer_queue_draw (renderer);
+}
+
+static void
+set_background_gdk (GtkSourceGutterRenderer *renderer,
+ const GdkColor *color)
+{
+ if (!color)
+ {
+ set_background_gdk_set (renderer, FALSE);
+ }
+ else
+ {
+ renderer->priv->background_gdk = *color;
+ renderer->priv->background_set = TRUE;
+
+ gtk_source_gutter_renderer_queue_draw (renderer);
+ }
+}
+
+static void
+gtk_source_gutter_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRenderer *self = GTK_SOURCE_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_VISIBLE:
+ set_visible (self, g_value_get_boolean (value));
+ break;
+ case PROP_XPAD:
+ set_xpad (self, g_value_get_int (value));
+ break;
+ case PROP_YPAD:
+ set_ypad (self, g_value_get_int (value));
+ break;
+ case PROP_XALIGN:
+ set_xalign (self, g_value_get_float (value), TRUE);
+ break;
+ case PROP_YALIGN:
+ set_yalign (self, g_value_get_float (value), TRUE);
+ break;
+ case PROP_ALIGNMENT_MODE:
+ set_alignment_mode (self, g_value_get_enum (value));
+ break;
+ case PROP_VIEW:
+ self->priv->view = g_value_get_object (value);
+ break;
+ case PROP_WINDOW_TYPE:
+ self->priv->window_type = g_value_get_enum (value);
+ break;
+ case PROP_SIZE:
+ set_size (self, g_value_get_int (value));
+ break;
+ case PROP_BACKGROUND_GDK:
+ set_background_gdk (self,
+ g_value_get_boxed (value));
+ break;
+ case PROP_BACKGROUND_SET:
+ set_background_gdk_set (self,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_renderer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRenderer *self = GTK_SOURCE_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_VISIBLE:
+ g_value_set_boolean (value, self->priv->visible);
+ break;
+ case PROP_XPAD:
+ g_value_set_int (value, self->priv->xpad);
+ break;
+ case PROP_YPAD:
+ g_value_set_int (value, self->priv->ypad);
+ break;
+ case PROP_XALIGN:
+ g_value_set_float (value, self->priv->xalign);
+ break;
+ case PROP_YALIGN:
+ g_value_set_float (value, self->priv->yalign);
+ break;
+ case PROP_VIEW:
+ g_value_set_object (value, self->priv->view);
+ break;
+ case PROP_ALIGNMENT_MODE:
+ g_value_set_enum (value, self->priv->alignment_mode);
+ break;
+ case PROP_WINDOW_TYPE:
+ g_value_set_enum (value, self->priv->window_type);
+ break;
+ case PROP_SIZE:
+ g_value_set_int (value, self->priv->size);
+ break;
+ case PROP_BACKGROUND_GDK:
+ g_value_set_boxed (value, &self->priv->background_gdk);
+ break;
+ case PROP_BACKGROUND_SET:
+ g_value_set_boolean (value, self->priv->background_set);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+renderer_draw_impl (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ if (!renderer->priv->background_set)
+ {
+ return;
+ }
+
+ cairo_save (cr);
+
+ gdk_cairo_rectangle (cr, background_area);
+ gdk_cairo_set_source_color (cr, &renderer->priv->background_gdk);
+
+ cairo_fill (cr);
+ cairo_restore (cr);
+}
+
+static void
+gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_gutter_renderer_finalize;
+
+ object_class->get_property = gtk_source_gutter_renderer_get_property;
+ object_class->set_property = gtk_source_gutter_renderer_set_property;
+
+ klass->draw = renderer_draw_impl;
+
+ g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererPrivate));
+
+ /**
+ * GtkSourceGutterRenderer:visible:
+ *
+ * The visibility of the renderer.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_VISIBLE,
+ g_param_spec_boolean ("visible",
+ _("Visible"),
+ _("Visible"),
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer:xpad:
+ *
+ * The x-padding of the renderer.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_XPAD,
+ g_param_spec_int ("xpad",
+ _("X Padding"),
+ _("The x-padding"),
+ -1,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer:ypad:
+ *
+ * The y-padding of the renderer.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_YPAD,
+ g_param_spec_int ("ypad",
+ _("Y Padding"),
+ _("The y-padding"),
+ -1,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer:xalign:
+ *
+ * The x-alignment of the renderer.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_XALIGN,
+ g_param_spec_float ("xalign",
+ _("X Alignment"),
+ _("The x-alignment"),
+ -1,
+ 1,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer:yalign:
+ *
+ * The y-alignment of the renderer.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_YALIGN,
+ g_param_spec_float ("yalign",
+ _("Y Alignment"),
+ _("The y-alignment"),
+ -1,
+ 1,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer::activate:
+ * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ * @iter: a #GtkTextIter
+ * @area: a #GdkRectangle
+ * @event: the event that caused the activation
+ *
+ * The ::activate signal is emitted when the renderer is
+ * activated.
+ *
+ */
+ signals[ACTIVATE] =
+ g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, activate),
+ NULL,
+ NULL,
+ _gtksourceview_marshal_VOID__BOXED_BOXED_BOXED,
+ G_TYPE_NONE,
+ 3,
+ GTK_TYPE_TEXT_ITER,
+ GDK_TYPE_RECTANGLE,
+ GDK_TYPE_EVENT);
+
+ /**
+ * GtkSourceGutterRenderer::queue-draw:
+ * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ *
+ * The ::queue-draw signal is emitted when the renderer needs
+ * to be redrawn. Use #gtk_source_gutter_renderer_queue_draw
+ * to emit this signal from an implementation of the
+ * #GtkSourceGutterRenderer interface.
+ *
+ */
+ signals[QUEUE_DRAW] =
+ g_signal_new ("queue-draw",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, queue_draw),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * GtkSourceGutterRenderer::query-tooltip:
+ * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ * @iter: a #GtkTextIter
+ * @area: a #GdkRectangle
+ * @x: the x position (in window coordinates)
+ * @y: the y position (in window coordinates)
+ * @tooltip: a #GtkTooltip
+ *
+ * The ::query-tooltip signal is emitted when the renderer can
+ * show a tooltip.
+ *
+ */
+ signals[QUERY_TOOLTIP] =
+ g_signal_new ("query-tooltip",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_tooltip),
+ g_signal_accumulator_true_handled,
+ NULL,
+ _gtksourceview_marshal_BOOLEAN__BOXED_BOXED_INT_INT_OBJECT,
+ G_TYPE_BOOLEAN,
+ 5,
+ GTK_TYPE_TEXT_ITER,
+ GDK_TYPE_RECTANGLE,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ GTK_TYPE_TOOLTIP);
+
+ /**
+ * GtkSourceGutterRenderer::query-data:
+ * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ * @start: a #GtkTextIter
+ * @end: a #GtkTextIter
+ * @state: the renderer state
+ *
+ * The ::query-data signal is emitted when the renderer needs
+ * to be filled with data just before a cell is drawn. This can
+ * be used by general renderer implementations to allow render
+ * data to be filled in externally.
+ *
+ */
+ signals[QUERY_DATA] =
+ g_signal_new ("query-data",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_data),
+ NULL,
+ NULL,
+ _gtksourceview_marshal_VOID__BOXED_BOXED_FLAGS,
+ G_TYPE_NONE,
+ 3,
+ GTK_TYPE_TEXT_ITER,
+ GTK_TYPE_TEXT_ITER,
+ GTK_TYPE_SOURCE_GUTTER_RENDERER_STATE);
+
+ /**
+ * GtkSourceGutterRenderer::query-activatable:
+ * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ * @iter: a #GtkTextIter
+ * @area: a #GdkRectangle
+ * @event: the #GdkEvent that is causing the activatable query
+ *
+ * The ::query-activatable signal is emitted when the renderer
+ * can possibly be activated.
+ *
+ */
+ signals[QUERY_ACTIVATABLE] =
+ g_signal_new ("query-activatable",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_activatable),
+ g_signal_accumulator_true_handled,
+ NULL,
+ _gtksourceview_marshal_BOOLEAN__BOXED_BOXED_BOXED,
+ G_TYPE_BOOLEAN,
+ 3,
+ GTK_TYPE_TEXT_ITER,
+ GDK_TYPE_RECTANGLE,
+ GDK_TYPE_EVENT);
+
+ /**
+ * GtkSourceGutterRenderer:view:
+ *
+ * The view on which the renderer is placed.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_VIEW,
+ g_param_spec_object ("view",
+ _("The View"),
+ _("The view"),
+ GTK_TYPE_TEXT_VIEW,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GtkSourceGutterRenderer:alignment-mode:
+ *
+ * The alignment mode of the renderer. This can be used to indicate
+ * that in the case a cell spans multiple lines (due to text wrapping)
+ * the alignment should work on either the full cell, the first line
+ * or the last line.
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_ALIGNMENT_MODE,
+ g_param_spec_enum ("alignment-mode",
+ _("Alignment Mode"),
+ _("The alignment mode"),
+ GTK_TYPE_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE,
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * GtkSourceGutterRenderer:window-type:
+ *
+ * The window type of the view on which the renderer is placed (left,
+ * or right).
+ *
+ **/
+ g_object_class_install_property (object_class,
+ PROP_WINDOW_TYPE,
+ g_param_spec_enum ("window-type",
+ _("Window Type"),
+ _("The window type"),
+ GTK_TYPE_TEXT_WINDOW_TYPE,
+ GTK_TEXT_WINDOW_PRIVATE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_SIZE,
+ g_param_spec_int ("size",
+ _("Size"),
+ _("The size"),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_BACKGROUND_GDK,
+ g_param_spec_boxed ("background-gdk",
+ "Background GDK",
+ "The background color",
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+
+ g_object_class_install_property (object_class,
+ PROP_BACKGROUND_SET,
+ g_param_spec_boolean ("background-set",
+ "Background Set",
+ "Whether the background color is set",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+gtk_source_gutter_renderer_init (GtkSourceGutterRenderer *self)
+{
+ self->priv = GTK_SOURCE_GUTTER_RENDERER_GET_PRIVATE (self);
+}
+
+/**
+ * gtk_source_gutter_renderer_begin:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @cr: a #cairo_t
+ * @background_area: a #GdkRectangle
+ * @cell_area: a #GdkRectangle
+ * @start: a #GtkTextIter
+ * @end: a #GtkTextIter
+ *
+ * Called when drawing a region begins. The region to be drawn is indicated
+ * by @start and @end. The purpose is to allow the implementation to precompute
+ * some state before the ::draw method is called for each cell.
+ *
+ **/
+void
+gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (background_area != NULL);
+ g_return_if_fail (cell_area != NULL);
+ g_return_if_fail (start != NULL);
+ g_return_if_fail (end != NULL);
+
+ if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->begin)
+ {
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (
+ G_OBJECT_GET_CLASS (renderer))->begin (renderer,
+ cr,
+ background_area,
+ cell_area,
+ start,
+ end);
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_draw:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @cr: the cairo render context
+ * @background_area: a #GdkRectangle indicating the total area to be drawn
+ * @cell_area: a #GdkRectangle indicating the area to draw content
+ * @start: a #GtkTextIter
+ * @end: a #GtkTextIter
+ * @state: a #GtkSourceGutterRendererState
+ *
+ * Main renderering method. Implementations should implement this method to
+ * draw onto the cairo context. The @background_area indicates total area of
+ * the cell (without padding or margin) to be drawn. The @cell_area indicates
+ * the area where content can be drawn (text, images, etc).
+ *
+ * The @state argument indicates the current state of the renderer and should
+ * be taken into account to properly draw the different possible states
+ * (cursor, prelit, selected) if appropriate.
+ *
+ **/
+void
+gtk_source_gutter_renderer_draw (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (background_area != NULL);
+ g_return_if_fail (cell_area != NULL);
+ g_return_if_fail (start != NULL);
+ g_return_if_fail (end != NULL);
+
+ if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->draw)
+ {
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (
+ G_OBJECT_GET_CLASS (renderer))->draw (renderer,
+ cr,
+ background_area,
+ cell_area,
+ start,
+ end,
+ state);
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_end:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Called when drawing a region of lines has ended.
+ *
+ **/
+void
+gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ if (GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->end)
+ {
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (G_OBJECT_GET_CLASS (renderer))->end (renderer);
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_query_activatable:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @iter: a #GtkTextIter at the start of the line to be activated
+ * @area: a #GdkRectangle of the cell area to be activated
+ * @event: the event that triggered the query
+ *
+ * Get whether the renderer is activatable at the location in @event. This is
+ * called from #GtkSourceGutter to determine whether a renderer is activatable
+ * using the mouse pointer.
+ *
+ * Returns: %TRUE if the renderer can be activated, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (area != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ ret = FALSE;
+
+ g_signal_emit (renderer,
+ signals[QUERY_ACTIVATABLE],
+ 0,
+ iter,
+ area,
+ event,
+ &ret);
+
+ return ret;
+}
+
+/**
+ * gtk_source_gutter_renderer_activate:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @iter: a #GtkTextIter at the start of the line where the renderer is activated
+ * @area: a #GdkRectangle of the cell area where the renderer is activated
+ * @event: the event that triggered the activation
+ *
+ * Emits the ::activate signal of the renderer. This is called from
+ * #GtkSourceGutter and should never have to be called manually.
+ *
+ */
+void
+gtk_source_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (area != NULL);
+ g_return_if_fail (event != NULL);
+
+ g_signal_emit (renderer, signals[ACTIVATE], 0, iter, area, event);
+}
+
+/**
+ * gtk_source_gutter_renderer_queue_draw:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Emits the ::queue-draw signal of the renderer. Call this from an
+ * implementation to inform that the renderer has changed such that it needs
+ * to redraw.
+ *
+ **/
+void
+gtk_source_gutter_renderer_queue_draw (GtkSourceGutterRenderer *renderer)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ g_signal_emit (renderer, signals[QUEUE_DRAW], 0);
+}
+
+/**
+ * gtk_source_gutter_renderer_query_tooltip:
+ * @renderer: a #GtkSourceGutterRenderer.
+ * @iter: a #GtkTextIter.
+ * @area: a #GdkRectangle.
+ * @x: The x position of the tooltip.
+ * @y: The y position of the tooltip.
+ * @tooltip: a #GtkTooltip.
+ *
+ * Emits the ::query-tooltip signal. This function is called from
+ * #GtkSourceGutter. Implementations can override the default signal handler
+ * or can connect to the signal externally.
+ *
+ * Returns: %TRUE if the tooltip has been set, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ gint x,
+ gint y,
+ GtkTooltip *tooltip)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (area != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TOOLTIP (tooltip), FALSE);
+
+ ret = FALSE;
+
+ g_signal_emit (renderer,
+ signals[QUERY_TOOLTIP],
+ 0,
+ iter,
+ area,
+ x,
+ y,
+ tooltip,
+ &ret);
+
+ return ret;
+}
+
+/**
+ * gtk_source_gutter_renderer_query_data:
+ * @renderer: a #GtkSourceGutterRenderer.
+ * @start: a #GtkTextIter.
+ * @end: a #GtkTextIter.
+ * @state: a #GtkSourceGutterRendererState.
+ *
+ * Emit the ::query-data signal. This function is called to query for data
+ * just before rendering a cell. This is called from the #GtkSourceGutter.
+ * Implementations can override the default signal handler or can connect
+ * a signal handler externally to the ::query-data signal.
+ *
+ **/
+void
+gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+ g_return_if_fail (start != NULL);
+ g_return_if_fail (end != NULL);
+
+ g_signal_emit (renderer, signals[QUERY_DATA], 0, start, end, state);
+}
+
+/**
+ * gtk_source_gutter_renderer_set_visible:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @visible: the visibility
+ *
+ * Set whether the gutter renderer is visible.
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_visible (GtkSourceGutterRenderer *renderer,
+ gboolean visible)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ if (visible != renderer->priv->visible)
+ {
+ renderer->priv->visible = visible;
+
+ g_object_notify (G_OBJECT (renderer), "visible");
+
+ gtk_source_gutter_renderer_queue_draw (renderer);
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_get_visible:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get whether the gutter renderer is visible.
+ *
+ * Returns: %TRUE if the renderer is visible, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_get_visible (GtkSourceGutterRenderer *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+
+ return renderer->priv->visible;
+}
+
+/**
+ * gtk_source_gutter_renderer_set_padding:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xpad: the x-padding
+ * @ypad: the y-padding
+ *
+ * Set the padding of the gutter renderer. Both @xpad and @ypad can be
+ * -1, which means the values will not be changed (this allows changing only
+ * one of the values).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_padding (GtkSourceGutterRenderer *renderer,
+ gint xpad,
+ gint ypad)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ set_xpad (renderer, xpad);
+ set_ypad (renderer, ypad);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_padding:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xpad: (out caller-allocates) (allow-none): return location for the x-padding (can be %NULL)
+ * @ypad: (out caller-allocates) (allow-none): return location for the y-padding (can be %NULL)
+ *
+ * Get the x-padding and y-padding of the gutter renderer.
+ *
+ **/
+void
+gtk_source_gutter_renderer_get_padding (GtkSourceGutterRenderer *renderer,
+ gint *xpad,
+ gint *ypad)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ if (xpad)
+ {
+ *xpad = renderer->priv->xpad;
+ }
+
+ if (ypad)
+ {
+ *ypad = renderer->priv->ypad;
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_set_alignment:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xalign: the x-alignment
+ * @yalign: the y-alignment
+ *
+ * Set the alignment of the gutter renderer. Both @xalign and @yalign can be
+ * -1, which means the values will not be changed (this allows changing only
+ * one of the values).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_alignment (GtkSourceGutterRenderer *renderer,
+ gfloat xalign,
+ gfloat yalign)
+{
+ gboolean changed_x;
+ gboolean changed_y;
+
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ changed_x = set_xalign (renderer, xalign, FALSE);
+ changed_y = set_yalign (renderer, yalign, FALSE);
+
+ if (changed_x || changed_y)
+ {
+ gtk_source_gutter_renderer_queue_draw (renderer);
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_get_alignment:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @xalign: (out caller-allocates) (allow-none): return location for the x-alignment (can be %NULL)
+ * @yalign: (out caller-allocates) (allow-none): return location for the y-alignment (can be %NULL)
+ *
+ * Get the x-alignment and y-alignment of the gutter renderer.
+ *
+ **/
+void
+gtk_source_gutter_renderer_get_alignment (GtkSourceGutterRenderer *renderer,
+ gfloat *xalign,
+ gfloat *yalign)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ if (xalign)
+ {
+ *xalign = renderer->priv->xalign;
+ }
+
+ if (yalign)
+ {
+ *yalign = renderer->priv->yalign;
+ }
+}
+
+/**
+ * gtk_source_gutter_renderer_set_alignment_mode:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @mode: a #GtkSourceGutterRendererAlignmentMode
+ *
+ * Set the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see :xalign and :yalign).
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterRendererAlignmentMode mode)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ set_alignment_mode (renderer, mode);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_alignment_mode:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see :xalign and :yalign).
+ *
+ * Returns: a #GtkSourceGutterRendererAlignmentMode
+ *
+ **/
+GtkSourceGutterRendererAlignmentMode
+gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), 0);
+
+ return renderer->priv->alignment_mode;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_window_type:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the #GtkTextWindowType associated with the gutter renderer.
+ *
+ * Returns: a #GtkTextWindowType
+ *
+ **/
+GtkTextWindowType
+gtk_source_gutter_renderer_get_window_type (GtkSourceGutterRenderer *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), GTK_TEXT_WINDOW_PRIVATE);
+
+ return renderer->priv->window_type;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_view:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the view associated to the gutter renderer
+ *
+ * Returns: (transfer none): a #GtkTextView
+ *
+ **/
+GtkTextView *
+gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), NULL);
+
+ return renderer->priv->view;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_size:
+ * @renderer: a #GtkSourceGutterRenderer
+ *
+ * Get the size of the renderer.
+ *
+ * Returns: the size of the renderer.
+ *
+ **/
+gint
+gtk_source_gutter_renderer_get_size (GtkSourceGutterRenderer *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), 0);
+
+ return renderer->priv->size;
+}
+
+/**
+ * gtk_source_gutter_renderer_set_size:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @size: the size
+ *
+ * Sets the size of the renderer. A value of -1 specifies that the size
+ * is to be determined dynamically.
+ *
+ **/
+void
+gtk_source_gutter_renderer_set_size (GtkSourceGutterRenderer *renderer,
+ gint size)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ set_size (renderer, size);
+}
+
+/**
+ * gtk_source_gutter_renderer_get_background:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @color: (out caller-allocates) (allow-none): return value for a #GdkColor
+ *
+ * Get the background color of the renderer.
+ *
+ * Returns: %TRUE if the background color is set, %FALSE otherwise
+ *
+ **/
+gboolean
+gtk_source_gutter_renderer_get_background (GtkSourceGutterRenderer *renderer,
+ GdkColor *color)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer), FALSE);
+
+ if (color)
+ {
+ *color = renderer->priv->background_gdk;
+ }
+
+ return renderer->priv->background_set;
+}
+
+/**
+ * gtk_source_gutter_renderer_get_background:
+ * @renderer: a #GtkSourceGutterRenderer
+ * @color: (allow-none): a #GdkColor or %NULL
+ *
+ * Set the background color of the renderer. If @color is set to %NULL, the
+ * renderer will not have a background color.
+ *
+ */
+void
+gtk_source_gutter_renderer_set_background (GtkSourceGutterRenderer *renderer,
+ const GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER (renderer));
+
+ set_background_gdk (renderer, color);
+}
diff --git a/gtksourceview/gtksourcegutterrenderer.h b/gtksourceview/gtksourcegutterrenderer.h
new file mode 100644
index 0000000..862bd4f
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderer.h
@@ -0,0 +1,218 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- *
+ * gtksourcegutterrenderer.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_H__
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER (gtk_source_gutter_renderer_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRenderer))
+#define GTK_SOURCE_GUTTER_RENDERER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRenderer const))
+#define GTK_SOURCE_GUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER))
+#define GTK_SOURCE_GUTTER_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER, GtkSourceGutterRendererClass))
+
+typedef struct _GtkSourceGutterRenderer GtkSourceGutterRenderer;
+typedef struct _GtkSourceGutterRendererClass GtkSourceGutterRendererClass;
+typedef struct _GtkSourceGutterRendererPrivate GtkSourceGutterRendererPrivate;
+
+/**
+ * GtkSourceGutterRendererState:
+ *
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL: normal state
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR: area in the renderer represents the
+ * line on which the insert cursor is currently positioned
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT: the mouse pointer is currently
+ * over the activatable area of the renderer
+ * @GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED: area in the renderer represents
+ * a line in the buffer which contains part of the selection
+ **/
+typedef enum
+{
+ GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL = 0,
+ GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR = 1 << 0,
+ GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT = 1 << 1,
+ GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED = 1 << 2
+} GtkSourceGutterRendererState;
+
+typedef enum
+{
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST,
+} GtkSourceGutterRendererAlignmentMode;
+
+struct _GtkSourceGutterRenderer
+{
+ /*< private >*/
+ GInitiallyUnowned parent;
+
+ GtkSourceGutterRendererPrivate *priv;
+};
+
+struct _GtkSourceGutterRendererClass
+{
+ /*< private >*/
+ GInitiallyUnownedClass parent_class;
+
+ /*< public >*/
+ void (*begin) (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end);
+
+ void (*draw) (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state);
+
+ void (*end) (GtkSourceGutterRenderer *renderer);
+
+ /* Signal handlers */
+ gboolean (*query_activatable) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event);
+
+ void (*activate) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event);
+
+ void (*queue_draw) (GtkSourceGutterRenderer *renderer);
+
+ gboolean (*query_tooltip) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ gint x,
+ gint y,
+ GtkTooltip *tooltip);
+
+ void (*query_data) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state);
+};
+
+GType gtk_source_gutter_renderer_get_type (void) G_GNUC_CONST;
+
+void gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end);
+
+void gtk_source_gutter_renderer_draw (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state);
+
+void gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer);
+
+gint gtk_source_gutter_renderer_get_size (GtkSourceGutterRenderer *renderer);
+void gtk_source_gutter_renderer_set_size (GtkSourceGutterRenderer *renderer,
+ gint size);
+
+void gtk_source_gutter_renderer_set_visible (GtkSourceGutterRenderer *renderer,
+ gboolean visible);
+
+gboolean gtk_source_gutter_renderer_get_visible (GtkSourceGutterRenderer *renderer);
+
+void gtk_source_gutter_renderer_get_padding (GtkSourceGutterRenderer *renderer,
+ gint *xpad,
+ gint *ypad);
+
+void gtk_source_gutter_renderer_set_padding (GtkSourceGutterRenderer *renderer,
+ gint xpad,
+ gint ypad);
+
+void gtk_source_gutter_renderer_get_alignment (GtkSourceGutterRenderer *renderer,
+ gfloat *xalign,
+ gfloat *yalign);
+
+void gtk_source_gutter_renderer_set_alignment (GtkSourceGutterRenderer *renderer,
+ gfloat xalign,
+ gfloat yalign);
+
+void gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterRendererAlignmentMode mode);
+
+GtkTextWindowType
+ gtk_source_gutter_renderer_get_window_type (GtkSourceGutterRenderer *renderer);
+
+GtkTextView *gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer *renderer);
+
+GtkSourceGutterRendererAlignmentMode
+ gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer *renderer);
+
+gboolean gtk_source_gutter_renderer_get_background (GtkSourceGutterRenderer *renderer,
+ GdkColor *color);
+
+void gtk_source_gutter_renderer_set_background (GtkSourceGutterRenderer *renderer,
+ const GdkColor *color);
+
+/* Emits the 'activate' signal */
+void gtk_source_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event);
+
+/* Emits the 'query-activatable' signal */
+gboolean gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event);
+
+/* Emits the 'queue-draw' signal */
+void gtk_source_gutter_renderer_queue_draw (GtkSourceGutterRenderer *renderer);
+
+/* Emits the 'query-tooltip' signal */
+gboolean gtk_source_gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ gint x,
+ gint y,
+ GtkTooltip *tooltip);
+
+/* Emits the 'query-data' signal */
+void gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_H__ */
diff --git a/gtksourceview/gtksourcegutterrendererlines.c b/gtksourceview/gtksourcegutterrendererlines.c
new file mode 100644
index 0000000..b5a1030
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererlines.c
@@ -0,0 +1,344 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererlines.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtksourcegutterrendererlines.h"
+#include "gtksourceview.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesPrivate))
+
+struct _GtkSourceGutterRendererLinesPrivate
+{
+ GtkTextBuffer *buffer;
+
+ gint num_line_digits;
+
+ guint changed_handler_id;
+ guint buffer_notify_handler_id;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererLines, gtk_source_gutter_renderer_lines, GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT)
+
+static void
+gtk_source_gutter_renderer_lines_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_lines_parent_class)->finalize (object);
+}
+
+static void
+recalculate_size (GtkSourceGutterRendererLines *renderer)
+{
+ gint num_lines;
+ gint num_digits = 0;
+ gint num;
+
+ num_lines = gtk_text_buffer_get_line_count (renderer->priv->buffer);
+
+ num = num_lines;
+
+ while (num > 0)
+ {
+ num /= 10;
+ ++num_digits;
+ }
+
+ num_digits = MAX (num_digits, 2);
+
+ if (num_digits != renderer->priv->num_line_digits)
+ {
+ gchar *markup;
+ gint size;
+
+ renderer->priv->num_line_digits = num_digits;
+
+ num_lines = MAX (num_lines, 99);
+
+ markup = g_strdup_printf ("<b>%d</b>", num_lines);
+ gtk_source_gutter_renderer_text_measure_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
+ markup,
+ &size,
+ NULL);
+ g_free (markup);
+
+ gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (renderer),
+ size);
+ }
+}
+
+static void
+on_buffer_changed (GtkSourceBuffer *buffer,
+ GtkSourceGutterRendererLines *renderer)
+{
+ recalculate_size (renderer);
+}
+
+static void
+buffer_notify (GtkSourceGutterRendererLines *renderer,
+ gpointer where_the_object_was)
+{
+ renderer->priv->buffer = NULL;
+}
+
+static void
+set_buffer (GtkSourceGutterRendererLines *renderer,
+ GtkTextBuffer *buffer)
+{
+ if (renderer->priv->buffer)
+ {
+ g_signal_handler_disconnect (renderer->priv->buffer,
+ renderer->priv->changed_handler_id);
+
+ g_object_weak_unref (G_OBJECT (renderer->priv->buffer),
+ (GWeakNotify)buffer_notify,
+ renderer);
+
+ renderer->priv->buffer = NULL;
+ }
+
+ if (buffer)
+ {
+ renderer->priv->buffer = buffer;
+
+ renderer->priv->changed_handler_id =
+ g_signal_connect (renderer->priv->buffer,
+ "changed",
+ G_CALLBACK (on_buffer_changed),
+ renderer);
+
+ g_object_weak_ref (G_OBJECT (renderer->priv->buffer),
+ (GWeakNotify)buffer_notify,
+ renderer);
+
+ recalculate_size (renderer);
+ }
+}
+
+static void
+gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ gchar *text;
+ gint line;
+ gboolean current_line;
+
+ line = gtk_text_iter_get_line (start) + 1;
+
+ current_line = (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR) &&
+ gtk_text_view_get_cursor_visible (gtk_source_gutter_renderer_get_view (renderer));
+
+ if (current_line)
+ {
+ text = g_strdup_printf ("<b>%d</b>", line);
+ }
+ else
+ {
+ text = g_strdup_printf ("%d", line);
+ }
+
+ gtk_source_gutter_renderer_text_set_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
+ text,
+ -1);
+
+ g_free (text);
+}
+
+static void
+on_buffer_notify (GtkTextView *view,
+ GParamSpec *spec,
+ GtkSourceGutterRendererLines *renderer)
+{
+ set_buffer (renderer, gtk_text_view_get_buffer (view));
+}
+
+static void
+gtk_source_gutter_renderer_lines_dispose (GObject *object)
+{
+ GtkSourceGutterRenderer *renderer;
+ GtkSourceGutterRendererLines *lines;
+ GtkTextView *view;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER (object);
+ lines = GTK_SOURCE_GUTTER_RENDERER_LINES (object);
+
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ if (view != NULL && lines->priv->buffer_notify_handler_id != 0)
+ {
+ g_signal_handler_disconnect (view,
+ lines->priv->buffer_notify_handler_id);
+
+ lines->priv->buffer_notify_handler_id = 0;
+ }
+
+ set_buffer (lines, NULL);
+
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_lines_parent_class)->dispose (object);
+}
+
+static void
+extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
+ GtkTextIter *line_start)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+ GtkTextIter line_end;
+
+ gtk_text_buffer_get_selection_bounds (renderer->priv->buffer, &start, &end);
+
+ line_end = *line_start;
+
+ if (!gtk_text_iter_ends_line (&line_end))
+ {
+ gtk_text_iter_forward_to_line_end (&line_end);
+ }
+
+ if (gtk_text_iter_compare (&start, line_start) < 0)
+ {
+ gtk_text_buffer_select_range (renderer->priv->buffer,
+ &start,
+ &line_end);
+ }
+ else if (gtk_text_iter_compare (&end, &line_end) < 0)
+ {
+ /* if the selection is in this line, extend
+ * the selection to the whole line */
+ gtk_text_buffer_select_range (renderer->priv->buffer,
+ &line_end,
+ line_start);
+ }
+ else
+ {
+ gtk_text_buffer_select_range (renderer->priv->buffer,
+ &end,
+ line_start);
+ }
+}
+
+static void
+select_line (GtkSourceGutterRendererLines *renderer,
+ GtkTextIter *line_start)
+{
+ GtkTextIter iter;
+
+ iter = *line_start;
+
+ if (!gtk_text_iter_ends_line (&iter))
+ {
+ gtk_text_iter_forward_to_line_end (&iter);
+ }
+
+ /* Select the line, put the cursor at the end of the line */
+ gtk_text_buffer_select_range (renderer->priv->buffer, &iter, line_start);
+}
+
+static void
+gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *rect,
+ GdkEvent *event)
+{
+ GtkSourceGutterRendererLines *lines;
+
+ lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
+
+ if (event->type == GDK_BUTTON_PRESS && (event->button.button == 1))
+ {
+ if ((event->button.state & GDK_CONTROL_MASK) != 0)
+ {
+ /* Single click + Ctrl -> select the line */
+ select_line (lines, iter);
+ }
+ else if ((event->button.state & GDK_SHIFT_MASK) != 0)
+ {
+ /* Single click + Shift -> extended current
+ selection to include the clicked line */
+ extend_selection_to_line (lines, iter);
+ }
+ else
+ {
+ gtk_text_buffer_place_cursor (lines->priv->buffer, iter);
+ }
+ }
+ else if (event->type == GDK_2BUTTON_PRESS && (event->button.button == 1))
+ {
+ select_line (lines, iter);
+ }
+}
+
+static gboolean
+gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ return GTK_SOURCE_GUTTER_RENDERER_LINES (renderer)->priv->buffer != NULL;
+}
+
+static void
+gtk_source_gutter_renderer_lines_constructed (GObject *gobject)
+{
+ GtkSourceGutterRendererLines *lines;
+ GtkSourceGutterRenderer *renderer;
+ GtkTextView *view;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER (gobject);
+ lines = GTK_SOURCE_GUTTER_RENDERER_LINES (gobject);
+
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ lines->priv->buffer_notify_handler_id =
+ g_signal_connect (view,
+ "notify::buffer",
+ G_CALLBACK (on_buffer_notify),
+ lines);
+
+ set_buffer (lines, gtk_text_view_get_buffer (view));
+}
+
+static void
+gtk_source_gutter_renderer_lines_class_init (GtkSourceGutterRendererLinesClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+ object_class->finalize = gtk_source_gutter_renderer_lines_finalize;
+ object_class->dispose = gtk_source_gutter_renderer_lines_dispose;
+ object_class->constructed = gtk_source_gutter_renderer_lines_constructed;
+
+ renderer_class->query_data = gutter_renderer_query_data;
+ renderer_class->query_activatable = gutter_renderer_query_activatable;
+ renderer_class->activate = gutter_renderer_activate;
+
+ g_type_class_add_private (object_class, sizeof(GtkSourceGutterRendererLinesPrivate));
+}
+
+static void
+gtk_source_gutter_renderer_lines_init (GtkSourceGutterRendererLines *self)
+{
+ self->priv = GTK_SOURCE_GUTTER_RENDERER_LINES_GET_PRIVATE (self);
+}
+
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_lines_new ()
+{
+ return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, NULL);
+}
diff --git a/gtksourceview/gtksourcegutterrendererlines.h b/gtksourceview/gtksourcegutterrendererlines.h
new file mode 100644
index 0000000..eb7b265
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererlines.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererlines.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_LINES_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_LINES_H__
+
+#include <gtksourceview/gtksourcegutterrenderertext.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES (gtk_source_gutter_renderer_lines_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_LINES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLines))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLines const))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_LINES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_LINES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES))
+#define GTK_SOURCE_GUTTER_RENDERER_LINES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES, GtkSourceGutterRendererLinesClass))
+
+typedef struct _GtkSourceGutterRendererLines GtkSourceGutterRendererLines;
+typedef struct _GtkSourceGutterRendererLinesClass GtkSourceGutterRendererLinesClass;
+typedef struct _GtkSourceGutterRendererLinesPrivate GtkSourceGutterRendererLinesPrivate;
+
+struct _GtkSourceGutterRendererLines
+{
+ /*< private >*/
+ GtkSourceGutterRendererText parent;
+
+ GtkSourceGutterRendererLinesPrivate *priv;
+
+ /*< public >*/
+};
+
+struct _GtkSourceGutterRendererLinesClass
+{
+ /*< private >*/
+ GtkSourceGutterRendererTextClass parent_class;
+
+ /*< public >*/
+};
+
+GType gtk_source_gutter_renderer_lines_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_lines_new (void);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_LINES_H__ */
diff --git a/gtksourceview/gtksourcegutterrenderermarks.c b/gtksourceview/gtksourcegutterrenderermarks.c
new file mode 100644
index 0000000..bdd4018
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderermarks.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderermarks.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtksourcegutterrenderermarks.h"
+#include "gtksourceview.h"
+#include "gtksourcemarkcategory.h"
+
+#define COMPOSITE_ALPHA 225
+
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksPrivate))
+
+struct _GtkSourceGutterRendererMarksPrivate
+{
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererMarks, gtk_source_gutter_renderer_marks, GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF)
+
+static void
+gtk_source_gutter_renderer_marks_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_marks_parent_class)->finalize (object);
+}
+
+static gint
+sort_marks_by_priority (gconstpointer m1,
+ gconstpointer m2,
+ gpointer data)
+{
+ GtkSourceMark *mark1 = GTK_SOURCE_MARK (m1);
+ GtkSourceMark *mark2 = GTK_SOURCE_MARK (m2);
+ GtkSourceView *view = GTK_SOURCE_VIEW (data);
+ GtkTextIter iter1, iter2;
+ gint line1;
+ gint line2;
+
+ gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark1)),
+ &iter1,
+ GTK_TEXT_MARK (mark1));
+
+ gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark2)),
+ &iter2,
+ GTK_TEXT_MARK (mark2));
+
+ line1 = gtk_text_iter_get_line (&iter1);
+ line2 = gtk_text_iter_get_line (&iter2);
+
+ if (line1 == line2)
+ {
+ guint priority1;
+ guint priority2;
+
+ GtkSourceMarkCategory *c1;
+ GtkSourceMarkCategory *c2;
+
+ c1 = gtk_source_view_get_mark_category (view,
+ gtk_source_mark_get_category (mark1));
+
+ c2 = gtk_source_view_get_mark_category (view,
+ gtk_source_mark_get_category (mark2));
+
+ priority1 = gtk_source_mark_category_get_priority (c1);
+ priority2 = gtk_source_mark_category_get_priority (c2);
+
+ return priority1 - priority2;
+ }
+ else
+ {
+ return line2 - line1;
+ }
+}
+
+static int
+measure_line_height (GtkSourceView *view)
+{
+ PangoLayout *layout;
+ gint height = 12;
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "QWERTY");
+
+ if (layout)
+ {
+ pango_layout_get_pixel_size (layout, NULL, &height);
+ g_object_unref (layout);
+ }
+
+ return height - 2;
+}
+
+static GdkPixbuf *
+composite_marks (GtkSourceView *view,
+ GSList *marks,
+ gint size)
+{
+ GdkPixbuf *composite;
+ gint mark_width;
+ gint mark_height;
+
+ /* Draw the mark with higher priority */
+ marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
+
+ composite = NULL;
+ mark_width = 0;
+ mark_height = 0;
+
+ /* composite all the pixbufs for the marks present at the line */
+ do
+ {
+ GtkSourceMark *mark;
+ GtkSourceMarkCategory *category;
+
+ const GdkPixbuf *pixbuf;
+
+ mark = marks->data;
+ category = gtk_source_view_get_mark_category (view,
+ gtk_source_mark_get_category (mark));
+
+ pixbuf = gtk_source_mark_category_render_icon (category,
+ GTK_WIDGET (view),
+ size);
+
+ if (pixbuf != NULL)
+ {
+ if (composite == NULL)
+ {
+ composite = gdk_pixbuf_copy (pixbuf);
+ mark_width = gdk_pixbuf_get_width (composite);
+ mark_height = gdk_pixbuf_get_height (composite);
+ }
+ else
+ {
+ gint pixbuf_w;
+ gint pixbuf_h;
+
+ pixbuf_w = gdk_pixbuf_get_width (pixbuf);
+ pixbuf_h = gdk_pixbuf_get_height (pixbuf);
+
+ gdk_pixbuf_composite (pixbuf,
+ composite,
+ 0, 0,
+ mark_width, mark_height,
+ 0, 0,
+ (gdouble) pixbuf_w / mark_width,
+ (gdouble) pixbuf_h / mark_height,
+ GDK_INTERP_BILINEAR,
+ COMPOSITE_ALPHA);
+ }
+ }
+
+ marks = g_slist_next (marks);
+ }
+ while (marks);
+
+ return composite;
+}
+
+static void
+gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ GSList *marks;
+ GdkPixbuf *pixbuf = NULL;
+ gint size = 0;
+ GtkSourceView *view;
+ GtkSourceBuffer *buffer;
+
+ view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+ buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+ marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
+ start,
+ NULL);
+
+ if (marks != NULL)
+ {
+ size = measure_line_height (view);
+ pixbuf = composite_marks (view, marks, size);
+
+ g_slist_free (marks);
+ }
+
+ g_object_set (G_OBJECT (renderer),
+ "pixbuf", pixbuf,
+ "xpad", 2,
+ "ypad", 1,
+ "yalign", 0.0,
+ "xalign", 0.5,
+ NULL);
+}
+
+static gboolean
+set_tooltip_widget_from_marks (GtkSourceView *view,
+ GtkTooltip *tooltip,
+ GSList *marks)
+{
+ GtkWidget *vbox = NULL;
+
+ for (; marks; marks = g_slist_next (marks))
+ {
+ const gchar *category;
+ GtkSourceMark *mark;
+ GtkSourceMarkCategory *cat;
+ gchar *text;
+ gboolean ismarkup = FALSE;
+ GtkWidget *label;
+ GtkWidget *hbox;
+ const GdkPixbuf *pixbuf;
+ gint size;
+
+ mark = marks->data;
+ category = gtk_source_mark_get_category (mark);
+
+ cat = gtk_source_view_get_mark_category (view, category);
+
+ if (cat == NULL)
+ {
+ continue;
+ }
+
+ text = gtk_source_mark_category_get_tooltip_markup (cat,
+ mark);
+
+ if (text == NULL)
+ {
+ text = gtk_source_mark_category_get_tooltip_text (cat,
+ mark);
+ }
+ else
+ {
+ ismarkup = TRUE;
+ }
+
+ if (text == NULL)
+ {
+ continue;
+ }
+
+ if (vbox == NULL)
+ {
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox);
+ }
+
+ hbox = gtk_hbox_new (FALSE, 4);
+ gtk_widget_show (hbox);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new (NULL);
+
+ if (ismarkup)
+ {
+ gtk_label_set_markup (GTK_LABEL (label), text);
+ }
+ else
+ {
+ gtk_label_set_text (GTK_LABEL (label), text);
+ }
+
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+ gtk_widget_show (label);
+
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &size);
+ pixbuf = gtk_source_mark_category_render_icon (cat,
+ GTK_WIDGET (view),
+ size);
+
+ if (pixbuf != NULL)
+ {
+ GtkWidget *image;
+ PangoLayoutLine *line;
+ PangoRectangle rect;
+ GtkWidget *align;
+ GdkPixbuf *copy;
+
+ align = gtk_alignment_new (0, 0, 0, 0);
+ gtk_widget_show (align);
+
+ copy = gdk_pixbuf_copy (pixbuf);
+ image = gtk_image_new_from_pixbuf (copy);
+ g_object_unref (copy);
+
+ gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
+ gtk_widget_show (image);
+
+ /* Measure up to align exact */
+ line = pango_layout_get_line (gtk_label_get_layout (GTK_LABEL (label)), 0);
+ pango_layout_line_get_pixel_extents (line, NULL, &rect);
+
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align),
+ (rect.height > size ? rect.height - size : size - rect.height) - 1,
+ 0, 0, 0);
+ if (rect.height > size)
+ {
+ gtk_container_add (GTK_CONTAINER (align),
+ image);
+
+ image = align;
+ }
+ else if (size > rect.height)
+ {
+ gtk_container_add (GTK_CONTAINER (align),
+ label);
+ label = align;
+ }
+ else
+ {
+ gtk_widget_destroy (align);
+ }
+
+ gtk_box_pack_start (GTK_BOX (hbox),
+ image,
+ FALSE,
+ FALSE,
+ 0);
+ }
+
+ gtk_box_pack_end (GTK_BOX (hbox),
+ label,
+ TRUE,
+ TRUE,
+ 0);
+
+ if (g_slist_length (marks) != 1)
+ {
+ GtkWidget *separator;
+
+ separator = gtk_hseparator_new ();
+
+ gtk_widget_show (separator);
+
+ gtk_box_pack_start (GTK_BOX (vbox),
+ separator,
+ FALSE,
+ FALSE,
+ 0);
+ }
+
+ g_free (text);
+ }
+
+ if (vbox == NULL)
+ {
+ return FALSE;
+ }
+
+ gtk_tooltip_set_custom (tooltip, vbox);
+
+ return TRUE;
+}
+
+static gboolean
+gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ gint x,
+ gint y,
+ GtkTooltip *tooltip)
+{
+ GSList *marks;
+ GtkSourceView *view;
+ GtkSourceBuffer *buffer;
+
+ view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+ buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+
+ marks = gtk_source_buffer_get_source_marks_at_iter (buffer,
+ iter,
+ NULL);
+
+ if (marks != NULL)
+ {
+ marks = g_slist_sort_with_data (marks,
+ sort_marks_by_priority,
+ view);
+
+ marks = g_slist_reverse (marks);
+
+ return set_tooltip_widget_from_marks (view, tooltip, marks);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ return TRUE;
+}
+
+static void
+gtk_source_gutter_renderer_marks_constructed (GObject *object)
+{
+ GtkSourceGutterRendererMarks *renderer;
+ GtkSourceView *view;
+ GtkSourceGutterRenderer *r;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER_MARKS (object);
+ r = GTK_SOURCE_GUTTER_RENDERER (renderer);
+
+ view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (r));
+
+ gtk_source_gutter_renderer_set_size (r,
+ measure_line_height (view));
+}
+
+static void
+gtk_source_gutter_renderer_marks_class_init (GtkSourceGutterRendererMarksClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+ object_class->finalize = gtk_source_gutter_renderer_marks_finalize;
+ object_class->constructed = gtk_source_gutter_renderer_marks_constructed;
+
+ renderer_class->query_data = gutter_renderer_query_data;
+ renderer_class->query_tooltip = gutter_renderer_query_tooltip;
+ renderer_class->query_activatable = gutter_renderer_query_activatable;
+
+ /*g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererMarksPrivate));*/
+}
+
+static void
+gtk_source_gutter_renderer_marks_init (GtkSourceGutterRendererMarks *self)
+{
+ /*self->priv = GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_PRIVATE (self);*/
+}
+
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_marks_new ()
+{
+ return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, NULL);
+}
diff --git a/gtksourceview/gtksourcegutterrenderermarks.h b/gtksourceview/gtksourcegutterrenderermarks.h
new file mode 100644
index 0000000..80d063e
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderermarks.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderermarks.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__
+
+#include <gtksourceview/gtksourcegutterrendererpixbuf.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS (gtk_source_gutter_renderer_marks_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarks))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarks const))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_MARKS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_MARKS_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS))
+#define GTK_SOURCE_GUTTER_RENDERER_MARKS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS, GtkSourceGutterRendererMarksClass))
+
+typedef struct _GtkSourceGutterRendererMarks GtkSourceGutterRendererMarks;
+typedef struct _GtkSourceGutterRendererMarksClass GtkSourceGutterRendererMarksClass;
+typedef struct _GtkSourceGutterRendererMarksPrivate GtkSourceGutterRendererMarksPrivate;
+
+struct _GtkSourceGutterRendererMarks
+{
+ /*< private >*/
+ GtkSourceGutterRendererPixbuf parent;
+
+ GtkSourceGutterRendererMarksPrivate *priv;
+
+ /*< public >*/
+};
+
+struct _GtkSourceGutterRendererMarksClass
+{
+ /*< private >*/
+ GtkSourceGutterRendererPixbufClass parent_class;
+
+ /*< public >*/
+};
+
+GType gtk_source_gutter_renderer_marks_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_marks_new (void);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_MARKS_H__ */
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.c b/gtksourceview/gtksourcegutterrendererpixbuf.c
new file mode 100644
index 0000000..1b20b29
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.c
@@ -0,0 +1,477 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrendererpixbuf.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "gtksourcegutterrendererpixbuf.h"
+#include "gtksourceview-i18n.h"
+#include "gtksourcepixbufhelper.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufPrivate))
+
+struct _GtkSourceGutterRendererPixbufPrivate
+{
+ GtkSourcePixbufHelper *helper;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererPixbuf, gtk_source_gutter_renderer_pixbuf, GTK_TYPE_SOURCE_GUTTER_RENDERER)
+
+enum
+{
+ PROP_0,
+ PROP_PIXBUF,
+ PROP_STOCK_ID,
+ PROP_ICON_NAME,
+ PROP_GICON,
+ PROP_STOCK_DETAIL
+};
+
+static void
+center_on (GtkSourceGutterRenderer *renderer,
+ const GdkRectangle *cell_area,
+ GtkTextIter *iter,
+ gint width,
+ gint height,
+ gfloat xalign,
+ gfloat yalign,
+ gint *x,
+ gint *y)
+{
+ GdkRectangle location;
+ GtkTextView *view;
+
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ gtk_text_view_get_iter_location (view, iter, &location);
+
+ *x = cell_area->x + (cell_area->width - width) * xalign;
+ *y = cell_area->y + (location.height - height) * yalign;
+}
+
+static void
+gutter_renderer_pixbuf_draw (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ GtkSourceGutterRendererPixbuf *pix;
+ gint width;
+ gint height;
+ gfloat xalign;
+ gfloat yalign;
+ GtkSourceGutterRendererAlignmentMode mode;
+ GtkTextView *view;
+ gint x = 0;
+ gint y = 0;
+ GdkPixbuf *pixbuf;
+
+ /* Chain up to draw background */
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (
+ gtk_source_gutter_renderer_pixbuf_parent_class)->draw (renderer,
+ cr,
+ background_area,
+ cell_area,
+ start,
+ end,
+ state);
+
+ pix = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (renderer);
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ pixbuf = gtk_source_pixbuf_helper_render (pix->priv->helper,
+ GTK_WIDGET (view),
+ cell_area->width);
+
+ if (!pixbuf)
+ {
+ return;
+ }
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_width (pixbuf);
+
+ gtk_source_gutter_renderer_get_alignment (renderer,
+ &xalign,
+ &yalign);
+
+ mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
+
+ switch (mode)
+ {
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL:
+ x = cell_area->x + (cell_area->width - width) * xalign;
+ y = cell_area->y + (cell_area->height - height) * yalign;
+ break;
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST:
+ center_on (renderer,
+ cell_area,
+ start,
+ width,
+ height,
+ xalign,
+ yalign,
+ &x,
+ &y);
+ break;
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
+ center_on (renderer,
+ cell_area,
+ end,
+ width,
+ height,
+ xalign,
+ yalign,
+ &x,
+ &y);
+ break;
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
+ cairo_paint (cr);
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_finalize (GObject *object)
+{
+ GtkSourceGutterRendererPixbuf *renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+ gtk_source_pixbuf_helper_free (renderer->priv->helper);
+
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_pixbuf_parent_class)->finalize (object);
+}
+
+static void
+set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
+ GdkPixbuf *pixbuf)
+{
+ gtk_source_pixbuf_helper_set_pixbuf (renderer->priv->helper,
+ pixbuf);
+
+ g_object_notify (G_OBJECT (renderer), "pixbuf");
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_stock_id (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_id)
+{
+ gtk_source_pixbuf_helper_set_stock_id (renderer->priv->helper,
+ stock_id);
+
+ g_object_notify (G_OBJECT (renderer), "stock-id");
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_detail)
+{
+ gtk_source_pixbuf_helper_set_stock_detail (renderer->priv->helper,
+ stock_detail);
+
+ g_object_notify (G_OBJECT (renderer), "stock-detail");
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_gicon (GtkSourceGutterRendererPixbuf *renderer,
+ GIcon *icon)
+{
+ gtk_source_pixbuf_helper_set_gicon (renderer->priv->helper,
+ icon);
+
+ g_object_notify (G_OBJECT (renderer), "gicon");
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+static void
+set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *icon_name)
+{
+ gtk_source_pixbuf_helper_set_icon_name (renderer->priv->helper,
+ icon_name);
+
+ g_object_notify (G_OBJECT (renderer), "icon-name");
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
+}
+
+
+static void
+gtk_source_gutter_renderer_pixbuf_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRendererPixbuf *renderer;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+ switch (prop_id)
+ {
+ case PROP_PIXBUF:
+ set_pixbuf (renderer, g_value_get_object (value));
+ break;
+ case PROP_STOCK_ID:
+ set_stock_id (renderer, g_value_get_string (value));
+ break;
+ case PROP_STOCK_DETAIL:
+ set_stock_detail (renderer, g_value_get_string (value));
+ break;
+ case PROP_ICON_NAME:
+ set_icon_name (renderer, g_value_get_string (value));
+ break;
+ case PROP_GICON:
+ set_gicon (renderer, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRendererPixbuf *renderer;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+
+ switch (prop_id)
+ {
+ case PROP_PIXBUF:
+ g_value_set_object (value,
+ gtk_source_pixbuf_helper_get_pixbuf (renderer->priv->helper));
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_stock_id (renderer->priv->helper));
+ break;
+ case PROP_STOCK_DETAIL:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_stock_detail (renderer->priv->helper));
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_icon_name (renderer->priv->helper));
+ break;
+ case PROP_GICON:
+ g_value_set_object (value,
+ gtk_source_pixbuf_helper_get_gicon (renderer->priv->helper));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+ object_class->finalize = gtk_source_gutter_renderer_pixbuf_finalize;
+
+ object_class->get_property = gtk_source_gutter_renderer_pixbuf_get_property;
+ object_class->set_property = gtk_source_gutter_renderer_pixbuf_set_property;
+
+ renderer_class->draw = gutter_renderer_pixbuf_draw;
+
+ g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererPixbufPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_PIXBUF,
+ g_param_spec_object ("pixbuf",
+ _("Pixbuf"),
+ _("The pixbuf"),
+ GDK_TYPE_PIXBUF,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_STOCK_ID,
+ g_param_spec_string ("stock-id",
+ _("Stock Id"),
+ _("The stock id"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_STOCK_DETAIL,
+ g_param_spec_string ("stock-detail",
+ _("Stock Detail"),
+ _("The stock detail"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ _("Icon Name"),
+ _("The icon name"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_GICON,
+ g_param_spec_object ("gicon",
+ _("GIcon"),
+ _("The gicon"),
+ G_TYPE_ICON,
+ G_PARAM_READWRITE));
+}
+
+static void
+gtk_source_gutter_renderer_pixbuf_init (GtkSourceGutterRendererPixbuf *self)
+{
+ self->priv = GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_PRIVATE (self);
+
+ self->priv->helper = gtk_source_pixbuf_helper_new ();
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_new:
+ *
+ * Create a new #GtkSourceGutterRendererPixbuf.
+ *
+ * Returns: (transfer full): A #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_pixbuf_new ()
+{
+ return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, NULL);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
+ GdkPixbuf *pixbuf)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+ g_return_if_fail (renderer == NULL || GDK_IS_PIXBUF (pixbuf));
+
+ set_pixbuf (renderer, pixbuf);
+}
+
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_get_pixbuf:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ *
+ * Get the pixbuf of the renderer.
+ *
+ * Returns: (transfer none): a #GdkPixbuf
+ *
+ **/
+GdkPixbuf *
+gtk_source_gutter_renderer_pixbuf_get_pixbuf (GtkSourceGutterRendererPixbuf *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return gtk_source_pixbuf_helper_get_pixbuf (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_stock_id (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_id)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS (renderer));
+
+ set_stock_id (renderer, stock_id);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_stock_id (GtkSourceGutterRendererPixbuf *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return gtk_source_pixbuf_helper_get_stock_id (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_detail)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+
+ set_stock_detail (renderer, stock_detail);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_stock_detail (GtkSourceGutterRendererPixbuf *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return gtk_source_pixbuf_helper_get_stock_detail (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_gicon (GtkSourceGutterRendererPixbuf *renderer,
+ GIcon *icon)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+ g_return_if_fail (icon == NULL || G_IS_ICON (icon));
+
+ set_gicon (renderer, icon);
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_get_gicon:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ *
+ * Get the gicon of the renderer
+ *
+ * Returns: (transfer none): a #GIcon
+ *
+ **/
+GIcon *
+gtk_source_gutter_renderer_pixbuf_get_gicon (GtkSourceGutterRendererPixbuf *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return gtk_source_pixbuf_helper_get_gicon (renderer->priv->helper);
+}
+
+void
+gtk_source_gutter_renderer_pixbuf_set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *icon_name)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer));
+
+ set_icon_name (renderer, icon_name);
+}
+
+const gchar *
+gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf *renderer)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return gtk_source_pixbuf_helper_get_icon_name (renderer->priv->helper);
+}
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.h b/gtksourceview/gtksourcegutterrendererpixbuf.h
new file mode 100644
index 0000000..e4c1c74
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderertext.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_PIXBUF_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_PIXBUF_H__
+
+#include <gtksourceview/gtksourcegutterrenderer.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF (gtk_source_gutter_renderer_pixbuf_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbuf))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbuf const))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF))
+#define GTK_SOURCE_GUTTER_RENDERER_PIXBUF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_PIXBUF, GtkSourceGutterRendererPixbufClass))
+
+typedef struct _GtkSourceGutterRendererPixbuf GtkSourceGutterRendererPixbuf;
+typedef struct _GtkSourceGutterRendererPixbufClass GtkSourceGutterRendererPixbufClass;
+typedef struct _GtkSourceGutterRendererPixbufPrivate GtkSourceGutterRendererPixbufPrivate;
+
+struct _GtkSourceGutterRendererPixbuf
+{
+ /*< private >*/
+ GtkSourceGutterRenderer parent;
+
+ GtkSourceGutterRendererPixbufPrivate *priv;
+
+ /*< public >*/
+};
+
+struct _GtkSourceGutterRendererPixbufClass
+{
+ /*< private >*/
+ GtkSourceGutterRendererClass parent_class;
+
+ /*< public >*/
+};
+
+GType gtk_source_gutter_renderer_pixbuf_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_pixbuf_new (void);
+
+void gtk_source_gutter_renderer_pixbuf_set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
+ GdkPixbuf *pixbuf);
+
+GdkPixbuf *gtk_source_gutter_renderer_pixbuf_get_pixbuf (GtkSourceGutterRendererPixbuf *renderer);
+
+void gtk_source_gutter_renderer_pixbuf_set_stock_id (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_id);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_stock_id (GtkSourceGutterRendererPixbuf *renderer);
+
+void gtk_source_gutter_renderer_pixbuf_set_icon_size (GtkSourceGutterRendererPixbuf *renderer,
+ GtkIconSize size);
+
+GtkIconSize gtk_source_gutter_renderer_pixbuf_get_icon_size (GtkSourceGutterRendererPixbuf *renderer);
+
+void gtk_source_gutter_renderer_pixbuf_set_stock_detail (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *stock_detail);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_stock_detail (GtkSourceGutterRendererPixbuf *renderer);
+
+void gtk_source_gutter_renderer_pixbuf_set_gicon (GtkSourceGutterRendererPixbuf *renderer,
+ GIcon *icon);
+
+GIcon *gtk_source_gutter_renderer_pixbuf_get_gicon (GtkSourceGutterRendererPixbuf *renderer);
+
+void gtk_source_gutter_renderer_pixbuf_set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
+ const gchar *icon_name);
+
+const gchar *gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf *renderer);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__ */
diff --git a/gtksourceview/gtksourcegutterrenderertext.c b/gtksourceview/gtksourcegutterrenderertext.c
new file mode 100644
index 0000000..a36ef40
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderertext.c
@@ -0,0 +1,432 @@
+#include "gtksourcegutterrenderertext.h"
+#include "gtksourceview-i18n.h"
+
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextPrivate))
+
+struct _GtkSourceGutterRendererTextPrivate
+{
+ gchar *text;
+
+ PangoLayout *cached_layout;
+ PangoAttribute *fg_attr;
+ PangoAttrList *cached_attr_list;
+
+ guint is_markup : 1;
+};
+
+G_DEFINE_TYPE (GtkSourceGutterRendererText, gtk_source_gutter_renderer_text, GTK_TYPE_SOURCE_GUTTER_RENDERER)
+
+enum
+{
+ PROP_0,
+ PROP_MARKUP,
+ PROP_TEXT,
+};
+
+static void
+create_layout (GtkSourceGutterRendererText *renderer,
+ GtkWidget *widget)
+{
+ PangoLayout *layout;
+ PangoAttribute *attr;
+ GdkColor color;
+ GtkStyle *style;
+ PangoAttrList *attr_list;
+
+ layout = gtk_widget_create_pango_layout (widget, NULL);
+
+ style = gtk_widget_get_style (widget);
+ color = style->fg[GTK_STATE_NORMAL];
+
+ attr = pango_attr_foreground_new (color.red, color.green, color.blue);
+
+ attr->start_index = 0;
+ attr->end_index = G_MAXINT;
+
+ attr_list = pango_attr_list_new ();
+ pango_attr_list_insert (attr_list, attr);
+
+ renderer->priv->fg_attr = attr;
+ renderer->priv->cached_layout = layout;
+ renderer->priv->cached_attr_list = attr_list;
+}
+
+static void
+gutter_renderer_text_begin (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ GtkSourceGutterRendererText *text;
+
+ text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+
+ create_layout (text, GTK_WIDGET (gtk_source_gutter_renderer_get_view (renderer)));
+}
+
+static void
+center_on (GtkSourceGutterRenderer *renderer,
+ const GdkRectangle *cell_area,
+ GtkTextIter *iter,
+ gint width,
+ gint height,
+ gfloat xalign,
+ gfloat yalign,
+ gint *x,
+ gint *y)
+{
+ GdkRectangle location;
+ GtkTextView *view;
+
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ gtk_text_view_get_iter_location (view, iter, &location);
+
+ *x = cell_area->x + (cell_area->width - width) * xalign;
+ *y = cell_area->y + (location.height - height) * yalign;
+}
+
+static void
+gutter_renderer_text_draw (GtkSourceGutterRenderer *renderer,
+ cairo_t *cr,
+ const GdkRectangle *background_area,
+ const GdkRectangle *cell_area,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ GtkSourceGutterRendererText *text;
+ gint width;
+ gint height;
+ PangoAttrList *attr_list;
+ gfloat xalign;
+ gfloat yalign;
+ GtkSourceGutterRendererAlignmentMode mode;
+ GtkTextView *view;
+ gint x = 0;
+ gint y = 0;
+
+ /* Chain up to draw background */
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (
+ gtk_source_gutter_renderer_text_parent_class)->draw (renderer,
+ cr,
+ background_area,
+ cell_area,
+ start,
+ end,
+ state);
+
+ text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+ view = gtk_source_gutter_renderer_get_view (renderer);
+
+ if (text->priv->is_markup)
+ {
+ pango_layout_set_markup (text->priv->cached_layout,
+ text->priv->text,
+ -1);
+ }
+ else
+ {
+ pango_layout_set_text (text->priv->cached_layout,
+ text->priv->text,
+ -1);
+ }
+
+ attr_list = pango_layout_get_attributes (text->priv->cached_layout);
+
+ if (!attr_list)
+ {
+ pango_layout_set_attributes (text->priv->cached_layout,
+ pango_attr_list_copy (text->priv->cached_attr_list));
+ }
+ else
+ {
+ pango_attr_list_insert (attr_list,
+ pango_attribute_copy (text->priv->fg_attr));
+ }
+
+ pango_layout_get_size (text->priv->cached_layout, &width, &height);
+
+ width /= PANGO_SCALE;
+ height /= PANGO_SCALE;
+
+ gtk_source_gutter_renderer_get_alignment (renderer,
+ &xalign,
+ &yalign);
+
+ mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
+
+ switch (mode)
+ {
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL:
+ x = cell_area->x + (cell_area->width - width) * xalign;
+ y = cell_area->y + (cell_area->height - height) * yalign;
+ break;
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST:
+ center_on (renderer,
+ cell_area,
+ start,
+ width,
+ height,
+ xalign,
+ yalign,
+ &x,
+ &y);
+ break;
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
+ center_on (renderer,
+ cell_area,
+ end,
+ width,
+ height,
+ xalign,
+ yalign,
+ &x,
+ &y);
+ break;
+ }
+
+ gtk_paint_layout (gtk_widget_get_style (GTK_WIDGET (view)),
+ cr,
+ gtk_widget_get_state (GTK_WIDGET (view)),
+ TRUE,
+ GTK_WIDGET (view),
+ "gtksourcegutterrenderertext",
+ x,
+ y,
+ text->priv->cached_layout);
+}
+
+static void
+gutter_renderer_text_end (GtkSourceGutterRenderer *renderer)
+{
+ GtkSourceGutterRendererText *text;
+
+ text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
+
+ g_object_unref (text->priv->cached_layout);
+ text->priv->cached_layout = NULL;
+
+ pango_attr_list_unref (text->priv->cached_attr_list);
+ text->priv->cached_attr_list = NULL;
+
+ text->priv->fg_attr = NULL;
+}
+
+static void
+measure_text (GtkSourceGutterRendererText *renderer,
+ const gchar *markup,
+ const gchar *text,
+ gint *width,
+ gint *height)
+{
+ PangoLayout *layout;
+ gint w;
+ gint h;
+ GtkSourceGutterRenderer *r;
+ GtkTextView *view;
+
+ r = GTK_SOURCE_GUTTER_RENDERER (renderer);
+ view = gtk_source_gutter_renderer_get_view (r);
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
+
+ if (markup)
+ {
+ pango_layout_set_markup (layout,
+ markup,
+ -1);
+ }
+ else
+ {
+ pango_layout_set_text (layout,
+ text,
+ -1);
+ }
+
+ pango_layout_get_size (layout, &w, &h);
+
+ if (width)
+ {
+ *width = w / PANGO_SCALE;
+ }
+
+ if (height)
+ {
+ *height = h / PANGO_SCALE;
+ }
+
+ g_object_unref (layout);
+}
+
+void
+gtk_source_gutter_renderer_text_measure (GtkSourceGutterRendererText *renderer,
+ const gchar *text,
+ gint *width,
+ gint *height)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+ g_return_if_fail (text != NULL);
+
+ measure_text (renderer, NULL, text, width, height);
+}
+
+void
+gtk_source_gutter_renderer_text_measure_markup (GtkSourceGutterRendererText *renderer,
+ const gchar *markup,
+ gint *width,
+ gint *height)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+ g_return_if_fail (markup != NULL);
+
+ measure_text (renderer, markup, NULL, width, height);
+}
+
+static void
+gtk_source_gutter_renderer_text_finalize (GObject *object)
+{
+ GtkSourceGutterRendererText *renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+ g_free (renderer->priv->text);
+
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_text_parent_class)->finalize (object);
+}
+
+static void
+set_text (GtkSourceGutterRendererText *renderer,
+ const gchar *text,
+ gint length,
+ gboolean is_markup)
+{
+ g_free (renderer->priv->text);
+
+ renderer->priv->text = length >= 0 ? g_strndup (text, length) : g_strdup (text);
+ renderer->priv->is_markup = is_markup;
+}
+
+static void
+gtk_source_gutter_renderer_text_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRendererText *renderer;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MARKUP:
+ set_text (renderer, g_value_get_string (value), -1, TRUE);
+ break;
+ case PROP_TEXT:
+ set_text (renderer, g_value_get_string (value), -1, FALSE);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_renderer_text_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceGutterRendererText *renderer;
+
+ renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+
+ switch (prop_id)
+ {
+ case PROP_MARKUP:
+ g_value_set_string (value, renderer->priv->is_markup ? renderer->priv->text : NULL);
+ break;
+ case PROP_TEXT:
+ g_value_set_string (value, !renderer->priv->is_markup ? renderer->priv->text : NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_gutter_renderer_text_class_init (GtkSourceGutterRendererTextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+ object_class->finalize = gtk_source_gutter_renderer_text_finalize;
+
+ object_class->get_property = gtk_source_gutter_renderer_text_get_property;
+ object_class->set_property = gtk_source_gutter_renderer_text_set_property;
+
+ renderer_class->begin = gutter_renderer_text_begin;
+ renderer_class->draw = gutter_renderer_text_draw;
+ renderer_class->end = gutter_renderer_text_end;
+
+ g_type_class_add_private (object_class, sizeof (GtkSourceGutterRendererTextPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_MARKUP,
+ g_param_spec_string ("markup",
+ _("Markup"),
+ _("The markup"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_TEXT,
+ g_param_spec_string ("text",
+ _("Text"),
+ _("The text"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+gtk_source_gutter_renderer_text_init (GtkSourceGutterRendererText *self)
+{
+ self->priv = GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_PRIVATE (self);
+
+ self->priv->is_markup = TRUE;
+}
+
+/**
+ * gtk_source_gutter_renderer_text_new:
+ *
+ * Create a new #GtkSourceGutterRendererText.
+ *
+ * Returns: (transfer full): A #GtkSourceGutterRenderer
+ *
+ **/
+GtkSourceGutterRenderer *
+gtk_source_gutter_renderer_text_new ()
+{
+ return g_object_new (GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, NULL);
+}
+
+void
+gtk_source_gutter_renderer_text_set_markup (GtkSourceGutterRendererText *renderer,
+ const gchar *markup,
+ gint length)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+
+ set_text (renderer, markup, length, TRUE);
+}
+
+void
+gtk_source_gutter_renderer_text_set_text (GtkSourceGutterRendererText *renderer,
+ const gchar *text,
+ gint length)
+{
+ g_return_if_fail (GTK_IS_SOURCE_GUTTER_RENDERER_TEXT (renderer));
+
+ set_text (renderer, text, length, FALSE);
+}
diff --git a/gtksourceview/gtksourcegutterrenderertext.h b/gtksourceview/gtksourcegutterrenderertext.h
new file mode 100644
index 0000000..0bb5791
--- /dev/null
+++ b/gtksourceview/gtksourcegutterrenderertext.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcegutterrenderertext.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__
+#define __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__
+
+#include <gtksourceview/gtksourcegutterrenderer.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT (gtk_source_gutter_renderer_text_get_type ())
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererText))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererText const))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextClass))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT))
+#define GTK_IS_SOURCE_GUTTER_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT))
+#define GTK_SOURCE_GUTTER_RENDERER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_GUTTER_RENDERER_TEXT, GtkSourceGutterRendererTextClass))
+
+typedef struct _GtkSourceGutterRendererText GtkSourceGutterRendererText;
+typedef struct _GtkSourceGutterRendererTextClass GtkSourceGutterRendererTextClass;
+typedef struct _GtkSourceGutterRendererTextPrivate GtkSourceGutterRendererTextPrivate;
+
+struct _GtkSourceGutterRendererText
+{
+ /*< private >*/
+ GtkSourceGutterRenderer parent;
+
+ GtkSourceGutterRendererTextPrivate *priv;
+
+ /*< public >*/
+};
+
+struct _GtkSourceGutterRendererTextClass
+{
+ /*< private >*/
+ GtkSourceGutterRendererClass parent_class;
+
+ /*< public >*/
+};
+
+GType gtk_source_gutter_renderer_text_get_type (void) G_GNUC_CONST;
+
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_text_new (void);
+
+void gtk_source_gutter_renderer_text_set_markup (GtkSourceGutterRendererText *renderer,
+ const gchar *markup,
+ gint length);
+
+void gtk_source_gutter_renderer_text_set_text (GtkSourceGutterRendererText *renderer,
+ const gchar *text,
+ gint length);
+
+void gtk_source_gutter_renderer_text_measure (GtkSourceGutterRendererText *renderer,
+ const gchar *text,
+ gint *width,
+ gint *height);
+
+void gtk_source_gutter_renderer_text_measure_markup (GtkSourceGutterRendererText *renderer,
+ const gchar *markup,
+ gint *width,
+ gint *height);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_GUTTER_RENDERER_TEXT_H__ */
diff --git a/gtksourceview/gtksourcemarkcategory.c b/gtksourceview/gtksourcemarkcategory.c
new file mode 100644
index 0000000..1caaa77
--- /dev/null
+++ b/gtksourceview/gtksourcemarkcategory.c
@@ -0,0 +1,571 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcemarkcategory.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtksourcemarkcategory.h"
+#include "gtksourceview-i18n.h"
+#include "gtksourcepixbufhelper.h"
+#include "gtksourceview-marshal.h"
+
+#define GTK_SOURCE_MARK_CATEGORY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryPrivate))
+
+struct _GtkSourceMarkCategoryPrivate
+{
+ gchar *id;
+ GdkColor background;
+ gint priority;
+
+ GtkSourcePixbufHelper *helper;
+
+ guint background_set : 1;
+};
+
+G_DEFINE_TYPE (GtkSourceMarkCategory, gtk_source_mark_category, G_TYPE_OBJECT)
+
+enum
+{
+ PROP_0,
+ PROP_ID,
+ PROP_BACKGROUND,
+ PROP_PRIORITY,
+ PROP_STOCK_ID,
+ PROP_STOCK_DETAIL,
+ PROP_PIXBUF,
+ PROP_ICON_NAME,
+ PROP_GICON
+};
+
+enum
+{
+ QUERY_TOOLTIP_TEXT,
+ QUERY_TOOLTIP_MARKUP,
+ NUM_SIGNALS
+};
+
+static guint signals[NUM_SIGNALS] = {0,};
+
+static void
+gtk_source_mark_category_finalize (GObject *object)
+{
+ GtkSourceMarkCategory *category = GTK_SOURCE_MARK_CATEGORY (object);
+
+ gtk_source_pixbuf_helper_free (category->priv->helper);
+
+ G_OBJECT_CLASS (gtk_source_mark_category_parent_class)->finalize (object);
+}
+
+static void
+set_background (GtkSourceMarkCategory *category,
+ const GdkColor *color)
+{
+ if (color)
+ {
+ category->priv->background = *color;
+ }
+
+ category->priv->background_set = color != NULL;
+
+ g_object_notify (G_OBJECT (category), "background");
+}
+
+static void
+set_priority (GtkSourceMarkCategory *category,
+ gint priority)
+{
+ if (category->priv->priority == priority)
+ {
+ return;
+ }
+
+ category->priv->priority = priority;
+ g_object_notify (G_OBJECT (category), "priority");
+}
+
+static void
+set_stock_id (GtkSourceMarkCategory *category,
+ const gchar *stock_id)
+{
+ if (g_strcmp0 (gtk_source_pixbuf_helper_get_stock_id (category->priv->helper),
+ stock_id) == 0)
+ {
+ return;
+ }
+
+ gtk_source_pixbuf_helper_set_stock_id (category->priv->helper,
+ stock_id);
+
+ g_object_notify (G_OBJECT (category), "stock-id");
+}
+
+static void
+set_stock_detail (GtkSourceMarkCategory *category,
+ const gchar *stock_detail)
+{
+ if (g_strcmp0 (gtk_source_pixbuf_helper_get_stock_detail (category->priv->helper),
+ stock_detail) == 0)
+ {
+ return;
+ }
+
+ gtk_source_pixbuf_helper_set_stock_detail (category->priv->helper,
+ stock_detail);
+
+ g_object_notify (G_OBJECT (category), "stock-detail");
+}
+
+static void
+set_icon_name (GtkSourceMarkCategory *category,
+ const gchar *icon_name)
+{
+ if (g_strcmp0 (gtk_source_pixbuf_helper_get_icon_name (category->priv->helper),
+ icon_name) == 0)
+ {
+ return;
+ }
+
+ gtk_source_pixbuf_helper_set_icon_name (category->priv->helper,
+ icon_name);
+
+ g_object_notify (G_OBJECT (category), "icon-name");
+}
+
+static void
+set_pixbuf (GtkSourceMarkCategory *category,
+ const GdkPixbuf *pixbuf)
+{
+ if (gtk_source_pixbuf_helper_get_pixbuf (category->priv->helper) == pixbuf)
+ {
+ return;
+ }
+
+ gtk_source_pixbuf_helper_set_pixbuf (category->priv->helper,
+ pixbuf);
+
+ g_object_notify (G_OBJECT (category), "pixbuf");
+}
+
+static void
+set_gicon (GtkSourceMarkCategory *category,
+ GIcon *gicon)
+{
+ if (gtk_source_pixbuf_helper_get_gicon (category->priv->helper) == gicon)
+ {
+ return;
+ }
+
+ gtk_source_pixbuf_helper_set_gicon (category->priv->helper,
+ gicon);
+
+ g_object_notify (G_OBJECT (category), "gicon");
+}
+
+static void
+gtk_source_mark_category_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceMarkCategory *self = GTK_SOURCE_MARK_CATEGORY (object);
+
+ switch (prop_id)
+ {
+ case PROP_ID:
+ self->priv->id = g_value_dup_string (value);
+ break;
+ case PROP_BACKGROUND:
+ set_background (self, g_value_get_boxed (value));
+ break;
+ case PROP_PRIORITY:
+ set_priority (self, g_value_get_int (value));
+ break;
+ case PROP_STOCK_ID:
+ set_stock_id (self, g_value_get_string (value));
+ break;
+ case PROP_STOCK_DETAIL:
+ set_stock_detail (self, g_value_get_string (value));
+ break;
+ case PROP_PIXBUF:
+ set_pixbuf (self, g_value_get_object (value));
+ break;
+ case PROP_ICON_NAME:
+ set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_GICON:
+ set_gicon (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_mark_category_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceMarkCategory *self = GTK_SOURCE_MARK_CATEGORY (object);
+
+ switch (prop_id)
+ {
+ case PROP_ID:
+ g_value_set_string (value, self->priv->id);
+ break;
+ case PROP_BACKGROUND:
+ if (self->priv->background_set)
+ {
+ g_value_set_boxed (value, &self->priv->background);
+ }
+ else
+ {
+ g_value_set_boxed (value, NULL);
+ }
+ break;
+ case PROP_PRIORITY:
+ g_value_set_int (value, self->priv->priority);
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_stock_id (self->priv->helper));
+ break;
+ case PROP_PIXBUF:
+ g_value_set_object (value,
+ gtk_source_pixbuf_helper_get_pixbuf (self->priv->helper));
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_icon_name (self->priv->helper));
+ break;
+ case PROP_GICON:
+ g_value_set_object (value,
+ gtk_source_pixbuf_helper_get_gicon (self->priv->helper));
+ break;
+ case PROP_STOCK_DETAIL:
+ g_value_set_string (value,
+ gtk_source_pixbuf_helper_get_stock_detail (self->priv->helper));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_source_mark_category_class_init (GtkSourceMarkCategoryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_source_mark_category_finalize;
+
+ object_class->get_property = gtk_source_mark_category_get_property;
+ object_class->set_property = gtk_source_mark_category_set_property;
+
+ g_type_class_add_private (object_class, sizeof(GtkSourceMarkCategoryPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_ID,
+ g_param_spec_string ("id",
+ _("Id"),
+ _("The id"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_BACKGROUND,
+ g_param_spec_boxed ("background",
+ _("Background"),
+ _("The background"),
+ GDK_TYPE_COLOR,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_PRIORITY,
+ g_param_spec_int ("priority",
+ _("Priority"),
+ _("The priority"),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_STOCK_ID,
+ g_param_spec_string ("stock-id",
+ _("Stock Id"),
+ _("The stock id"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_PIXBUF,
+ g_param_spec_object ("pixbuf",
+ _("Pixbuf"),
+ _("The pixbuf"),
+ GDK_TYPE_PIXBUF,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ _("Icon Name"),
+ _("The icon name"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_GICON,
+ g_param_spec_object ("gicon",
+ _("GIcon"),
+ _("The GIcon"),
+ G_TYPE_ICON,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_STOCK_DETAIL,
+ g_param_spec_string ("stock-detail",
+ _("Stock Detail"),
+ _("The stock detail"),
+ NULL,
+ G_PARAM_READWRITE));
+
+ signals[QUERY_TOOLTIP_TEXT] =
+ g_signal_new ("query-tooltip-text",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ _gtksourceview_marshal_STRING__OBJECT,
+ G_TYPE_STRING,
+ 1,
+ GTK_TYPE_SOURCE_MARK);
+
+ signals[QUERY_TOOLTIP_MARKUP] =
+ g_signal_new ("query-tooltip-markup",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ _gtksourceview_marshal_STRING__OBJECT,
+ G_TYPE_STRING,
+ 1,
+ GTK_TYPE_SOURCE_MARK);
+}
+
+static void
+gtk_source_mark_category_init (GtkSourceMarkCategory *self)
+{
+ self->priv = GTK_SOURCE_MARK_CATEGORY_GET_PRIVATE (self);
+
+ self->priv->helper = gtk_source_pixbuf_helper_new ();
+}
+
+GtkSourceMarkCategory *
+gtk_source_mark_category_new (const gchar *id)
+{
+ return g_object_new (GTK_TYPE_SOURCE_MARK_CATEGORY,
+ "id", id,
+ NULL);
+}
+
+const gchar *
+gtk_source_mark_category_get_id (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return category->priv->id;
+}
+
+void
+gtk_source_mark_category_set_background (GtkSourceMarkCategory *category,
+ const GdkColor *background)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_background (category, background);
+}
+
+gboolean
+gtk_source_mark_category_get_background (GtkSourceMarkCategory *category,
+ GdkColor *background)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), FALSE);
+
+ *background = category->priv->background;
+ return category->priv->background_set;
+}
+
+void
+gtk_source_mark_category_set_priority (GtkSourceMarkCategory *category,
+ gint priority)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_priority (category, priority);
+}
+
+gint
+gtk_source_mark_category_get_priority (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), 0);
+
+ return category->priv->priority;
+}
+
+void
+gtk_source_mark_category_set_stock_id (GtkSourceMarkCategory *category,
+ const gchar *stock_id)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_stock_id (category, stock_id);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_id (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return gtk_source_pixbuf_helper_get_stock_id (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_stock_detail (GtkSourceMarkCategory *category,
+ const gchar *stock_detail)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_stock_detail (category, stock_detail);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_detail (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return gtk_source_pixbuf_helper_get_stock_detail (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_icon_name (GtkSourceMarkCategory *category,
+ const gchar *icon_name)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_icon_name (category, icon_name);
+}
+
+const gchar *
+gtk_source_mark_category_get_stock_icon_name (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return gtk_source_pixbuf_helper_get_icon_name (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_gicon (GtkSourceMarkCategory *category,
+ GIcon *gicon)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_gicon (category, gicon);
+}
+
+/**
+ * gtk_source_mark_category_get_gicon:
+ * @category: a #GtkSourceMarkCategory
+ *
+ * Get the #GIcon associated with the mark category.
+ *
+ * Returns: (transfer none): A #GIcon
+ *
+ **/
+GIcon *
+gtk_source_mark_category_get_gicon (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return gtk_source_pixbuf_helper_get_gicon (category->priv->helper);
+}
+
+void
+gtk_source_mark_category_set_pixbuf (GtkSourceMarkCategory *category,
+ const GdkPixbuf *pixbuf)
+{
+ g_return_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category));
+
+ set_pixbuf (category, pixbuf);
+}
+
+const GdkPixbuf *
+gtk_source_mark_category_get_pixbuf (GtkSourceMarkCategory *category)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+
+ return gtk_source_pixbuf_helper_get_pixbuf (category->priv->helper);
+}
+
+const GdkPixbuf *
+gtk_source_mark_category_render_icon (GtkSourceMarkCategory *category,
+ GtkWidget *widget,
+ gint size)
+{
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+ g_return_val_if_fail (size > 0, NULL);
+
+ return gtk_source_pixbuf_helper_render (category->priv->helper,
+ widget,
+ size);
+}
+
+gchar *
+gtk_source_mark_category_get_tooltip_text (GtkSourceMarkCategory *category,
+ GtkSourceMark *mark)
+{
+ gchar *ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK (mark), NULL);
+
+ ret = NULL;
+ g_signal_emit (category, signals[QUERY_TOOLTIP_TEXT], 0, mark, &ret);
+
+ return ret;
+}
+
+gchar *
+gtk_source_mark_category_get_tooltip_markup (GtkSourceMarkCategory *category,
+ GtkSourceMark *mark)
+{
+ gchar *ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK_CATEGORY (category), NULL);
+ g_return_val_if_fail (GTK_IS_SOURCE_MARK (mark), NULL);
+
+ ret = NULL;
+ g_signal_emit (category, signals[QUERY_TOOLTIP_MARKUP], 0, mark, &ret);
+
+ return ret;
+}
+
diff --git a/gtksourceview/gtksourcemarkcategory.h b/gtksourceview/gtksourcemarkcategory.h
new file mode 100644
index 0000000..1249f9f
--- /dev/null
+++ b/gtksourceview/gtksourcemarkcategory.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcemarkcategory.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_MARK_CATEGORY_H__
+#define __GTK_SOURCE_MARK_CATEGORY_H__
+
+#include <gtk/gtk.h>
+#include <gtksourceview/gtksourcemark.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SOURCE_MARK_CATEGORY (gtk_source_mark_category_get_type ())
+#define GTK_SOURCE_MARK_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategory))
+#define GTK_SOURCE_MARK_CATEGORY_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategory const))
+#define GTK_SOURCE_MARK_CATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryClass))
+#define GTK_IS_SOURCE_MARK_CATEGORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY))
+#define GTK_IS_SOURCE_MARK_CATEGORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_MARK_CATEGORY))
+#define GTK_SOURCE_MARK_CATEGORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOURCE_MARK_CATEGORY, GtkSourceMarkCategoryClass))
+
+typedef struct _GtkSourceMarkCategory GtkSourceMarkCategory;
+typedef struct _GtkSourceMarkCategoryClass GtkSourceMarkCategoryClass;
+typedef struct _GtkSourceMarkCategoryPrivate GtkSourceMarkCategoryPrivate;
+
+struct _GtkSourceMarkCategory
+{
+ /*< private >*/
+ GObject parent;
+
+ GtkSourceMarkCategoryPrivate *priv;
+
+ /*< public >*/
+};
+
+struct _GtkSourceMarkCategoryClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /*< public >*/
+};
+
+GType gtk_source_mark_category_get_type (void) G_GNUC_CONST;
+
+GtkSourceMarkCategory *gtk_source_mark_category_new (const gchar *id);
+
+const gchar *gtk_source_mark_category_get_id (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_background (GtkSourceMarkCategory *category,
+ const GdkColor *background);
+
+gboolean gtk_source_mark_category_get_background (GtkSourceMarkCategory *category,
+ GdkColor *background);
+
+void gtk_source_mark_category_set_priority (GtkSourceMarkCategory *category,
+ gint priority);
+
+gint gtk_source_mark_category_get_priority (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_stock_id (GtkSourceMarkCategory *category,
+ const gchar *stock_id);
+const gchar *gtk_source_mark_category_get_stock_id (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_stock_detail (GtkSourceMarkCategory *category,
+ const gchar *stock_detail);
+const gchar *gtk_source_mark_category_get_stock_detail (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_icon_name (GtkSourceMarkCategory *category,
+ const gchar *icon_name);
+const gchar *gtk_source_mark_category_get_stock_icon_name (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_gicon (GtkSourceMarkCategory *category,
+ GIcon *gicon);
+GIcon *gtk_source_mark_category_get_gicon (GtkSourceMarkCategory *category);
+
+void gtk_source_mark_category_set_pixbuf (GtkSourceMarkCategory *category,
+ const GdkPixbuf *pixbuf);
+const GdkPixbuf *gtk_source_mark_category_get_pixbuf (GtkSourceMarkCategory *category);
+
+const GdkPixbuf *gtk_source_mark_category_render_icon (GtkSourceMarkCategory *category,
+ GtkWidget *widget,
+ gint size);
+
+gchar *gtk_source_mark_category_get_tooltip_text (GtkSourceMarkCategory *category,
+ GtkSourceMark *mark);
+
+gchar *gtk_source_mark_category_get_tooltip_markup (GtkSourceMarkCategory *category,
+ GtkSourceMark *mark);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_MARK_CATEGORY_H__ */
diff --git a/gtksourceview/gtksourcepixbufhelper.c b/gtksourceview/gtksourcepixbufhelper.c
new file mode 100644
index 0000000..6c5413b
--- /dev/null
+++ b/gtksourceview/gtksourcepixbufhelper.c
@@ -0,0 +1,352 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcepixbufhelper.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "gtksourcepixbufhelper.h"
+
+typedef enum
+{
+ ICON_TYPE_PIXBUF,
+ ICON_TYPE_STOCK,
+ ICON_TYPE_GICON,
+ ICON_TYPE_NAME
+} IconType;
+
+struct _GtkSourcePixbufHelper
+{
+ GdkPixbuf *cached_pixbuf;
+ IconType type;
+
+ GdkPixbuf *pixbuf;
+ gchar *icon_name;
+ gchar *stock_id;
+ gchar *stock_detail;
+ GIcon *gicon;
+};
+
+GtkSourcePixbufHelper *
+gtk_source_pixbuf_helper_new (void)
+{
+ return g_slice_new0 (GtkSourcePixbufHelper);
+}
+
+void
+gtk_source_pixbuf_helper_free (GtkSourcePixbufHelper *helper)
+{
+ if (helper->pixbuf)
+ {
+ g_object_unref (helper->pixbuf);
+ }
+
+ if (helper->cached_pixbuf)
+ {
+ g_object_unref (helper->cached_pixbuf);
+ }
+
+ if (helper->gicon)
+ {
+ g_object_unref (helper->gicon);
+ }
+
+ g_free (helper->stock_id);
+ g_free (helper->stock_detail);
+ g_free (helper->icon_name);
+
+ g_slice_free (GtkSourcePixbufHelper, helper);
+}
+
+static void
+set_cache (GtkSourcePixbufHelper *helper,
+ GdkPixbuf *pixbuf)
+{
+ if (helper->cached_pixbuf)
+ {
+ g_object_unref (helper->cached_pixbuf);
+ helper->cached_pixbuf = NULL;
+ }
+
+ if (pixbuf)
+ {
+ helper->cached_pixbuf = pixbuf;
+ }
+}
+
+static void
+clear_cache (GtkSourcePixbufHelper *helper)
+{
+ set_cache (helper, NULL);
+}
+
+void
+gtk_source_pixbuf_helper_set_pixbuf (GtkSourcePixbufHelper *helper,
+ const GdkPixbuf *pixbuf)
+{
+ helper->type = ICON_TYPE_PIXBUF;
+
+ if (helper->pixbuf)
+ {
+ g_object_unref (helper->pixbuf);
+ helper->pixbuf = NULL;
+ }
+
+ if (pixbuf)
+ {
+ helper->pixbuf = gdk_pixbuf_copy (pixbuf);
+ }
+
+ clear_cache (helper);
+}
+
+GdkPixbuf *
+gtk_source_pixbuf_helper_get_pixbuf (GtkSourcePixbufHelper *helper)
+{
+ return helper->pixbuf;
+}
+
+void
+gtk_source_pixbuf_helper_set_stock_id (GtkSourcePixbufHelper *helper,
+ const gchar *stock_id)
+{
+ helper->type = ICON_TYPE_STOCK;
+
+ if (helper->stock_id)
+ {
+ g_free (helper->stock_id);
+ }
+
+ helper->stock_id = g_strdup (stock_id);
+
+ clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_stock_id (GtkSourcePixbufHelper *helper)
+{
+ return helper->stock_id;
+}
+
+void
+gtk_source_pixbuf_helper_set_stock_detail (GtkSourcePixbufHelper *helper,
+ const gchar *detail)
+{
+ helper->type = ICON_TYPE_STOCK;
+
+ if (helper->stock_detail)
+ {
+ g_free (helper->stock_detail);
+ }
+
+ helper->stock_detail = g_strdup (detail);
+
+ clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_stock_detail (GtkSourcePixbufHelper *helper)
+{
+ return helper->stock_detail;
+}
+
+void
+gtk_source_pixbuf_helper_set_icon_name (GtkSourcePixbufHelper *helper,
+ const gchar *icon_name)
+{
+ helper->type = ICON_TYPE_STOCK;
+
+ if (helper->icon_name)
+ {
+ g_free (helper->icon_name);
+ }
+
+ helper->icon_name = g_strdup (icon_name);
+
+ clear_cache (helper);
+}
+
+const gchar *
+gtk_source_pixbuf_helper_get_icon_name (GtkSourcePixbufHelper *helper)
+{
+ return helper->icon_name;
+}
+
+void
+gtk_source_pixbuf_helper_set_gicon (GtkSourcePixbufHelper *helper,
+ GIcon *gicon)
+{
+ helper->type = ICON_TYPE_GICON;
+
+ if (helper->gicon)
+ {
+ g_object_unref (helper->gicon);
+ helper->gicon = NULL;
+ }
+
+ if (gicon)
+ {
+ helper->gicon = g_object_ref (gicon);
+ }
+
+ clear_cache (helper);
+}
+
+GIcon *
+gtk_source_pixbuf_helper_get_gicon (GtkSourcePixbufHelper *helper)
+{
+ return helper->gicon;
+}
+
+static void
+from_pixbuf (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size)
+{
+ if (helper->pixbuf == NULL)
+ {
+ return;
+ }
+
+ if (gdk_pixbuf_get_width (helper->pixbuf) <= size)
+ {
+ if (!helper->cached_pixbuf)
+ {
+ set_cache (helper, gdk_pixbuf_copy (helper->pixbuf));
+ }
+
+ return;
+ }
+
+ /* Make smaller */
+ set_cache (helper, gdk_pixbuf_scale_simple (helper->pixbuf,
+ size,
+ size,
+ GDK_INTERP_BILINEAR));
+}
+
+static void
+from_stock (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size)
+{
+ GtkIconSize icon_size;
+ gchar *name;
+
+ name = g_strdup_printf ("GtkSourcePixbufHelper%d", size);
+
+ icon_size = gtk_icon_size_from_name (name);
+
+ if (icon_size == GTK_ICON_SIZE_INVALID)
+ {
+ icon_size = gtk_icon_size_register (name, size, size);
+ }
+
+ g_free (name);
+
+ set_cache (helper, gtk_widget_render_icon (widget,
+ helper->stock_id,
+ icon_size,
+ helper->stock_detail));
+}
+static void
+from_gicon (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size)
+{
+ GdkScreen *screen;
+ GtkIconTheme *icon_theme;
+ GtkSettings *settings;
+ GtkIconInfo *info;
+ GtkIconLookupFlags flags;
+
+ screen = gtk_widget_get_screen (widget);
+ icon_theme = gtk_icon_theme_get_for_screen (screen);
+ settings = gtk_settings_get_for_screen (screen);
+
+ flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
+ info = gtk_icon_theme_lookup_by_gicon (icon_theme,
+ helper->gicon,
+ size,
+ flags);
+
+ if (info)
+ {
+ set_cache (helper, gtk_icon_info_load_icon (info, NULL));
+ }
+}
+
+static void
+from_name (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size)
+{
+ GdkScreen *screen;
+ GtkIconTheme *icon_theme;
+ GtkSettings *settings;
+ GtkIconInfo *info;
+ GtkIconLookupFlags flags;
+
+ screen = gtk_widget_get_screen (widget);
+ icon_theme = gtk_icon_theme_get_for_screen (screen);
+ settings = gtk_settings_get_for_screen (screen);
+
+ flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
+ info = gtk_icon_theme_lookup_icon (icon_theme,
+ helper->icon_name,
+ size,
+ flags);
+
+ if (info)
+ {
+ set_cache (helper, gtk_icon_info_load_icon (info, NULL));
+ }
+}
+
+GdkPixbuf *
+gtk_source_pixbuf_helper_render (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size)
+{
+ if (helper->cached_pixbuf &&
+ gdk_pixbuf_get_width (helper->cached_pixbuf) == size)
+ {
+ return helper->cached_pixbuf;
+ }
+
+ switch (helper->type)
+ {
+ case ICON_TYPE_PIXBUF:
+ from_pixbuf (helper, widget, size);
+ break;
+ case ICON_TYPE_STOCK:
+ from_stock (helper, widget, size);
+ break;
+ case ICON_TYPE_GICON:
+ from_gicon (helper, widget, size);
+ break;
+ case ICON_TYPE_NAME:
+ from_name (helper, widget, size);
+ break;
+ }
+
+ return helper->cached_pixbuf;
+}
+
diff --git a/gtksourceview/gtksourcepixbufhelper.h b/gtksourceview/gtksourcepixbufhelper.h
new file mode 100644
index 0000000..c78c34b
--- /dev/null
+++ b/gtksourceview/gtksourcepixbufhelper.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*-
+ * gtksourcepixbufhelper.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2010 - Jesse van den Kieboom
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_PIXBUF_HELPER_H__
+#define __GTK_SOURCE_PIXBUF_HELPER_H__
+
+#include <gtk/gtk.h>
+
+typedef struct _GtkSourcePixbufHelper GtkSourcePixbufHelper;
+
+GtkSourcePixbufHelper *gtk_source_pixbuf_helper_new (void);
+void gtk_source_pixbuf_helper_free (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_pixbuf (GtkSourcePixbufHelper *helper,
+ const GdkPixbuf *pixbuf);
+
+GdkPixbuf *gtk_source_pixbuf_helper_get_pixbuf (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_stock_id (GtkSourcePixbufHelper *helper,
+ const gchar *stock_id);
+
+const gchar *gtk_source_pixbuf_helper_get_stock_id (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_stock_detail (GtkSourcePixbufHelper *helper,
+ const gchar *stock_id);
+
+const gchar *gtk_source_pixbuf_helper_get_stock_detail (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_icon_name (GtkSourcePixbufHelper *helper,
+ const gchar *icon_name);
+
+const gchar *gtk_source_pixbuf_helper_get_icon_name (GtkSourcePixbufHelper *helper);
+
+void gtk_source_pixbuf_helper_set_gicon (GtkSourcePixbufHelper *helper,
+ GIcon *gicon);
+
+GIcon *gtk_source_pixbuf_helper_get_gicon (GtkSourcePixbufHelper *helper);
+
+GdkPixbuf *gtk_source_pixbuf_helper_render (GtkSourcePixbufHelper *helper,
+ GtkWidget *widget,
+ gint size);
+
+#endif /* __GTK_SOURCE_PIXBUF_HELPER_H__ */
+
diff --git a/gtksourceview/gtksourceview-marshal.list b/gtksourceview/gtksourceview-marshal.list
index ee06a8a..1ef9b81 100644
--- a/gtksourceview/gtksourceview-marshal.list
+++ b/gtksourceview/gtksourceview-marshal.list
@@ -16,3 +16,8 @@ BOOL:OBJECT,BOXED,OBJECT
VOID:BOXED,POINTER
VOID:INT
VOID:BOXED,INT
+VOID:BOXED,BOXED,BOXED
+BOOLEAN:BOXED,BOXED,INT,INT,OBJECT
+VOID:BOXED,BOXED,FLAGS
+BOOLEAN:BOXED,BOXED,BOXED
+STRING:OBJECT
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 92c2677..79bfc7c 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -41,6 +41,8 @@
#include "gtksourcecompletion-private.h"
#include "gtksourcecompletionutils.h"
#include "gtksourcegutter-private.h"
+#include "gtksourcegutterrendererlines.h"
+#include "gtksourcegutterrenderermarks.h"
/**
* SECTION:view
@@ -75,7 +77,6 @@
#define PROFILE(x)
#endif
-#define COMPOSITE_ALPHA 225
#define GUTTER_PIXMAP 16
#define DEFAULT_TAB_WIDTH 8
#define MAX_TAB_WIDTH 32
@@ -149,14 +150,15 @@ struct _GtkSourceViewPrivate
GtkSourceGutter *left_gutter;
GtkSourceGutter *right_gutter;
- GtkCellRenderer *line_renderer;
- GtkCellRenderer *marks_renderer;
+ GtkSourceGutterRenderer *line_renderer;
+ GtkSourceGutterRenderer *marks_renderer;
GdkColor current_line_color;
GtkSourceCompletion *completion;
gulong notify_buffer_id;
+ gint num_line_digits;
guint current_line_color_set : 1;
};
@@ -184,26 +186,6 @@ typedef enum
ICON_TYPE_NAME
} IconType;
-typedef struct
-{
- gint priority;
-
- IconType icon_type;
- GdkPixbuf *icon_pixbuf;
- gchar *icon_stock;
- gchar *icon_name;
-
- GdkPixbuf *cached_icon;
-
- GtkSourceViewMarkTooltipFunc tooltip_func;
- gpointer tooltip_data;
- GDestroyNotify tooltip_data_notify;
-
- GdkColor background;
- guint background_set : 1;
- guint tooltip_markup : 1;
-} MarkCategory;
-
/* Prototypes. */
static GObject *gtk_source_view_constructor (GType type,
guint n_construct_properties,
@@ -272,17 +254,6 @@ static void gtk_source_view_style_set (GtkWidget *widg
static void gtk_source_view_realize (GtkWidget *widget);
static void gtk_source_view_update_style_scheme (GtkSourceView *view);
-static MarkCategory *
- gtk_source_view_get_mark_category (GtkSourceView *view,
- GtkSourceMark *mark);
-
-static MarkCategory *
- gtk_source_view_ensure_category (GtkSourceView *view,
- const gchar *name);
-static MarkCategory *
- mark_category_new (gint priority);
-static void mark_category_free (MarkCategory *cat);
-
/* Private functions. */
static void
gtk_source_view_class_init (GtkSourceViewClass *klass)
@@ -948,633 +919,18 @@ notify_buffer (GtkSourceView *view)
gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
}
-static gint
-sort_marks_by_priority (gconstpointer m1,
- gconstpointer m2,
- gpointer data)
-{
- GtkSourceMark *mark1 = GTK_SOURCE_MARK (m1);
- GtkSourceMark *mark2 = GTK_SOURCE_MARK (m2);
- GtkSourceView *view = GTK_SOURCE_VIEW (data);
- GtkTextIter iter1, iter2;
- gint line1;
- gint line2;
-
- gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark1)),
- &iter1,
- GTK_TEXT_MARK (mark1));
- gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark2)),
- &iter2,
- GTK_TEXT_MARK (mark2));
-
- line1 = gtk_text_iter_get_line (&iter1);
- line2 = gtk_text_iter_get_line (&iter2);
-
- if (line1 == line2)
- {
- guint priority1 = gtk_source_view_get_mark_category_priority (view,
- gtk_source_mark_get_category (mark1));
- guint priority2 = gtk_source_view_get_mark_category_priority (view,
- gtk_source_mark_get_category (mark2));
-
- return priority1 - priority2;
- }
- else
- {
- return line2 - line1;
- }
-}
-
-static GdkPixbuf *
-get_icon_from_stock (GtkSourceView *view,
- const gchar *stock_id,
- gint size)
-{
- gchar *sizename;
- GtkIconSize iconsize;
-
- /* Check special icon size */
- sizename = g_strdup_printf ("GtkSourceMarkCategoryIcon%d", size);
- iconsize = gtk_icon_size_from_name (sizename);
-
- if (iconsize == GTK_ICON_SIZE_INVALID)
- {
- iconsize = gtk_icon_size_register (sizename, size, size);
- }
-
- g_free (sizename);
-
- if (iconsize == GTK_ICON_SIZE_INVALID)
- {
- return NULL;
- }
-
- return gtk_widget_render_icon (GTK_WIDGET (view),
- stock_id,
- iconsize,
- NULL);
-}
-
-static GdkPixbuf *
-get_icon_from_name (GtkSourceView *view,
- const gchar *name,
- gint size)
-{
- GtkIconTheme *theme;
-
- theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (view)));
-
- return gtk_icon_theme_load_icon (theme,
- name,
- size,
- GTK_ICON_LOOKUP_USE_BUILTIN |
- GTK_ICON_LOOKUP_FORCE_SIZE,
- NULL);
-}
-
static void
-remove_cached_category_icon (MarkCategory *category)
+gutter_renderer_marks_activate (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ const GdkRectangle *area,
+ GdkEvent *event,
+ GtkSourceView *view)
{
- if (category->cached_icon != NULL)
- {
- g_object_unref (category->cached_icon);
- category->cached_icon = NULL;
- }
-}
-
-static GdkPixbuf *
-get_mark_category_pixbuf (GtkSourceView *view,
- const gchar *category,
- gint size)
-{
- MarkCategory *cat;
-
- cat = g_hash_table_lookup (view->priv->mark_categories, category);
-
- if (cat == NULL)
- {
- return NULL;
- }
-
- if (cat->cached_icon &&
- (gdk_pixbuf_get_height (cat->cached_icon) == size ||
- gdk_pixbuf_get_width (cat->cached_icon) == size))
- {
- return cat->cached_icon;
- }
-
- /* Regenerate icon */
- remove_cached_category_icon (cat);
-
- switch (cat->icon_type)
- {
- case ICON_TYPE_NONE:
- break;
- case ICON_TYPE_PIXBUF:
- if (cat->icon_pixbuf == NULL)
- {
- return NULL;
- }
-
- if (gdk_pixbuf_get_width (cat->icon_pixbuf) <= size &&
- gdk_pixbuf_get_height (cat->icon_pixbuf) <= size)
- {
- cat->cached_icon = g_object_ref (cat->icon_pixbuf);
- }
- else
- {
- cat->cached_icon = gdk_pixbuf_scale_simple (cat->icon_pixbuf,
- size,
- size,
- GDK_INTERP_BILINEAR);
- }
- break;
- case ICON_TYPE_STOCK:
- cat->cached_icon = get_icon_from_stock (view,
- cat->icon_stock,
- size);
- break;
- case ICON_TYPE_NAME:
- cat->cached_icon = get_icon_from_name (view,
- cat->icon_name,
- size);
- break;
- default:
- g_return_val_if_reached (NULL);
- }
-
- return cat->cached_icon;
-}
-
-static GdkPixbuf *
-composite_marks (GtkSourceView *view,
- GSList *marks,
- gint size)
-{
- GdkPixbuf *composite;
- gint mark_width, mark_height;
-
- /* Draw the mark with higher priority */
- marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
-
- composite = NULL;
- mark_width = mark_height = 0;
-
- /* composite all the pixbufs for the marks present at the line */
- do
- {
- GtkSourceMark *mark;
- GdkPixbuf *pixbuf;
-
- mark = marks->data;
-
- pixbuf = get_mark_category_pixbuf (view,
- gtk_source_mark_get_category (mark),
- size);
-
- if (pixbuf != NULL)
- {
- if (composite == NULL)
- {
- composite = gdk_pixbuf_copy (pixbuf);
- mark_width = gdk_pixbuf_get_width (composite);
- mark_height = gdk_pixbuf_get_height (composite);
- }
- else
- {
- gint pixbuf_w;
- gint pixbuf_h;
-
- pixbuf_w = gdk_pixbuf_get_width (pixbuf);
- pixbuf_h = gdk_pixbuf_get_height (pixbuf);
-
- gdk_pixbuf_composite (pixbuf,
- composite,
- 0, 0,
- mark_width, mark_height,
- 0, 0,
- (double) pixbuf_w / mark_width,
- (double) pixbuf_h / mark_height,
- GDK_INTERP_BILINEAR,
- COMPOSITE_ALPHA);
- }
- }
-
- marks = g_slist_next (marks);
- }
- while (marks);
-
- return composite;
-}
-
-static int
-measure_line_height (GtkSourceView *view)
-{
- PangoLayout *layout;
- gint height = 12;
-
- layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "QWERTY");
-
- if (layout)
- {
- pango_layout_get_pixel_size (layout, NULL, &height);
- g_object_unref (layout);
- }
-
- return height - 2;
-}
-
-static void
-marks_renderer_data_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- gint line_number,
- gboolean current_line,
- GtkSourceView *view)
-{
- GSList *marks;
- GdkPixbuf *pixbuf = NULL;
- int size = 0;
-
- if (view->priv->source_buffer)
- {
- marks = gtk_source_buffer_get_source_marks_at_line (view->priv->source_buffer,
- line_number,
- NULL);
-
- if (marks != NULL)
- {
- GtkTextIter iter;
-
- gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (view->priv->source_buffer),
- &iter,
- line_number);
-
- if (size == 0)
- {
- size = measure_line_height (view);
- }
-
- /* draw marks for the line */
- pixbuf = composite_marks (view, marks, size);
- g_slist_free (marks);
- }
- }
-
- g_object_set (G_OBJECT (renderer),
- "pixbuf", pixbuf,
- "xpad", 2,
- "ypad", 1,
- "yalign", 0.0,
- "xalign", 0.5,
- "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
- NULL);
-}
-
-static void
-line_renderer_data_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- gint line_number,
- gboolean current_line,
- GtkSourceView *view)
-{
- int weight;
- gchar *text;
- GtkStyle *style;
-
- if (current_line && gtk_text_view_get_cursor_visible (GTK_TEXT_VIEW (view)))
- {
- weight = PANGO_WEIGHT_BOLD;
- }
- else
- {
- weight = PANGO_WEIGHT_NORMAL;
- }
-
- text = g_strdup_printf ("%d", line_number + 1);
- g_object_set (G_OBJECT (renderer),
- "text", text,
- "xalign", 1.0,
- "yalign", 0.0,
- "xpad", 2,
- "ypad", 0,
- "weight", weight,
- "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
- NULL);
-
- style = gtk_widget_get_style (GTK_WIDGET (view));
- if (style != NULL)
- {
- g_object_set (G_OBJECT (renderer),
- "foreground-gdk", &style->fg[GTK_STATE_NORMAL],
- NULL);
- }
-
- g_object_set (G_OBJECT (renderer),
- "background-set", FALSE,
- NULL);
-
- g_free (text);
-}
-
-static void
-line_renderer_size_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceView *view)
-{
- gchar *text;
- gint count;
-
- count = gtk_text_buffer_get_line_count (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- text = g_strdup_printf ("%d", MAX(99, count));
-
- /* measure with bold, just in case font is rendered larger */
- g_object_set (G_OBJECT (renderer),
- "text", text,
- "xpad", 2,
- "ypad", 0,
- "weight", PANGO_WEIGHT_BOLD,
- NULL);
-
- g_free (text);
-}
-
-static void
-extend_selection_to_line (GtkTextBuffer *buf, GtkTextIter *line_start)
-{
- GtkTextIter start;
- GtkTextIter end;
- GtkTextIter line_end;
-
- gtk_text_buffer_get_selection_bounds (buf, &start, &end);
-
- line_end = *line_start;
-
- if (!gtk_text_iter_ends_line (&line_end))
- gtk_text_iter_forward_to_line_end (&line_end);
-
- if (gtk_text_iter_compare (&start, line_start) < 0)
- {
- gtk_text_buffer_select_range (buf, &start, &line_end);
- }
- else if (gtk_text_iter_compare (&end, &line_end) < 0)
- {
- /* if the selection is in this line, extend
- * the selection to the whole line */
- gtk_text_buffer_select_range (buf, &line_end, line_start);
- }
- else
- {
- gtk_text_buffer_select_range (buf, &end, line_start);
- }
-}
-
-static void
-select_line (GtkTextBuffer *buf, GtkTextIter *line_start)
-{
- GtkTextIter iter;
-
- iter = *line_start;
-
- if (!gtk_text_iter_ends_line (&iter))
- gtk_text_iter_forward_to_line_end (&iter);
-
- /* Select the line, put the cursor at the end of the line */
- gtk_text_buffer_select_range (buf, &iter, line_start);
-}
-
-static void
-marks_renderer_size_func (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkSourceView *view)
-{
- gint size;
- GdkPixbuf *pixbuf;
-
- size = measure_line_height (view);
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- TRUE,
- 8,
- size,
- size);
-
- g_object_set (G_OBJECT (renderer),
- "pixbuf", pixbuf,
- "xpad", 2,
- "ypad", 1,
- NULL);
-
- g_object_unref (pixbuf);
-}
-
-static void
-renderer_activated (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkTextIter *iter,
- GdkEvent *event,
- GtkSourceView *view)
-{
- if (renderer == view->priv->marks_renderer)
- {
- g_signal_emit (view,
- signals[LINE_MARK_ACTIVATED],
- 0,
- iter,
- event);
- }
- else if (renderer == view->priv->line_renderer)
- {
- GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
- if (event->type == GDK_BUTTON_PRESS && (event->button.button == 1))
- {
- if ((event->button.state & GDK_CONTROL_MASK) != 0)
- {
- /* Single click + Ctrl -> select the line */
- select_line (buf, iter);
- }
- else if ((event->button.state & GDK_SHIFT_MASK) != 0)
- {
- /* Single click + Shift -> extended current
- selection to include the clicked line */
- extend_selection_to_line (buf, iter);
- }
- else
- {
- gtk_text_buffer_place_cursor (buf, iter);
- }
- }
- else if (event->type == GDK_2BUTTON_PRESS && (event->button.button == 1))
- {
- select_line (buf, iter);
- }
- }
-}
-
-static gboolean
-set_tooltip_widget_from_marks (GtkSourceView *view,
- GtkTooltip *tooltip,
- GSList *marks)
-{
- GtkWidget *vbox = NULL;
-
- while (marks != NULL)
- {
- const gchar *category;
- GtkSourceMark *mark;
- MarkCategory *cat;
-
- mark = marks->data;
- category = gtk_source_mark_get_category (mark);
-
- cat = gtk_source_view_get_mark_category (view, mark);
-
- if (cat != NULL && cat->tooltip_func != NULL)
- {
- gchar *text;
-
- text = cat->tooltip_func (mark, cat->tooltip_data);
- if (text != NULL)
- {
- GtkWidget *label;
- GtkWidget *hbox;
-
- if (vbox == NULL)
- {
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vbox);
- }
-
- hbox = gtk_hbox_new (FALSE, 4);
- gtk_widget_show (hbox);
- gtk_box_pack_start (GTK_BOX (vbox), hbox,
- FALSE, FALSE, 0);
-
- GdkPixbuf *pixbuf;
- gint size;
-
- label = gtk_label_new (NULL);
-
- if (cat->tooltip_markup)
- gtk_label_set_markup (GTK_LABEL (label), text);
- else
- gtk_label_set_text (GTK_LABEL (label), text);
-
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
- gtk_widget_show (label);
-
- gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &size);
- pixbuf = get_mark_category_pixbuf (view, category, size);
-
- if (pixbuf != NULL)
- {
- GtkWidget *image;
- PangoLayoutLine *line;
- PangoRectangle rect;
- GtkWidget *align;
-
- align = gtk_alignment_new (0, 0, 0, 0);
- gtk_widget_show (align);
-
- image = gtk_image_new_from_pixbuf (pixbuf);
- gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
- gtk_widget_show (image);
-
- /* Measure up to align exact */
- line = pango_layout_get_line (gtk_label_get_layout (GTK_LABEL (label)), 0);
- pango_layout_line_get_pixel_extents (line, NULL, &rect);
-
- gtk_alignment_set_padding (GTK_ALIGNMENT (align),
- (rect.height > size ? rect.height - size : size - rect.height) - 1,
- 0, 0, 0);
- if (rect.height > size)
- {
- gtk_container_add (GTK_CONTAINER (align),
- image);
-
- image = align;
- }
- else if (size > rect.height)
- {
- gtk_container_add (GTK_CONTAINER (align),
- label);
- label = align;
- }
- else
- {
- gtk_widget_destroy (align);
- }
-
- gtk_box_pack_start (GTK_BOX (hbox),
- image,
- FALSE,
- FALSE,
- 0);
- }
-
- gtk_box_pack_end (GTK_BOX (hbox),
- label,
- TRUE,
- TRUE,
- 0);
-
- if (g_slist_length (marks) != 1)
- {
- GtkWidget *separator;
-
- separator = gtk_hseparator_new ();
- gtk_widget_show (separator);
- gtk_box_pack_start (GTK_BOX (vbox), separator,
- FALSE, FALSE, 0);
- }
-
- g_free (text);
- }
- }
-
- marks = g_slist_delete_link (marks, marks);
- }
-
- if (vbox == NULL)
- return FALSE;
-
- gtk_tooltip_set_custom (tooltip, vbox);
-
- return TRUE;
-}
-
-static gboolean
-renderer_query_tooltip (GtkSourceGutter *gutter,
- GtkCellRenderer *renderer,
- GtkTextIter *iter,
- GtkTooltip *tooltip,
- GtkSourceView *view)
-{
- GSList *marks;
- GtkSourceBuffer *buffer;
- gint line;
-
- if (renderer != view->priv->marks_renderer)
- {
- return FALSE;
- }
-
- buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- line = gtk_text_iter_get_line (iter);
-
- marks = gtk_source_buffer_get_source_marks_at_line (buffer,
- line,
- NULL);
-
- if (marks != NULL)
- {
- marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);
- marks = g_slist_reverse (marks);
-
- return set_tooltip_widget_from_marks (view, tooltip, marks);
- }
-
- return FALSE;
+ g_signal_emit (view,
+ signals[LINE_MARK_ACTIVATED],
+ 0,
+ iter,
+ event);
}
static void
@@ -1582,54 +938,30 @@ init_left_gutter (GtkSourceView *view)
{
GtkSourceGutter *gutter;
- view->priv->line_renderer = gtk_cell_renderer_text_new ();
- view->priv->marks_renderer = gtk_cell_renderer_pixbuf_new ();
-
gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
- gtk_source_gutter_insert (gutter,
- view->priv->line_renderer,
- GTK_SOURCE_VIEW_GUTTER_POSITION_LINES);
-
- gtk_source_gutter_insert (gutter,
- view->priv->marks_renderer,
- GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS);
-
- gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, 0, 0);
- gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, 0, 0);
-
- gtk_source_gutter_set_cell_data_func (gutter,
- view->priv->line_renderer,
- (GtkSourceGutterDataFunc)line_renderer_data_func,
- view,
- NULL);
-
- gtk_source_gutter_set_cell_size_func (gutter,
- view->priv->line_renderer,
- (GtkSourceGutterSizeFunc)line_renderer_size_func,
- view,
- NULL);
-
- gtk_source_gutter_set_cell_data_func (gutter,
- view->priv->marks_renderer,
- (GtkSourceGutterDataFunc)marks_renderer_data_func,
- view,
- NULL);
-
- gtk_source_gutter_set_cell_size_func (gutter,
- view->priv->marks_renderer,
- (GtkSourceGutterSizeFunc)marks_renderer_size_func,
- view,
- NULL);
-
- g_signal_connect (gutter,
- "cell-activated",
- G_CALLBACK (renderer_activated),
- view);
-
- g_signal_connect (gutter,
- "query-tooltip",
- G_CALLBACK (renderer_query_tooltip),
+ view->priv->line_renderer =
+ gtk_source_gutter_insert (gutter,
+ GTK_TYPE_SOURCE_GUTTER_RENDERER_LINES,
+ GTK_SOURCE_VIEW_GUTTER_POSITION_LINES,
+ "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ "yalign", 0.5,
+ "xalign", 1.0,
+ "xpad", 3,
+ NULL);
+
+ view->priv->marks_renderer =
+ gtk_source_gutter_insert (gutter,
+ GTK_TYPE_SOURCE_GUTTER_RENDERER_MARKS,
+ GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS,
+ "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ "yalign", 0.5,
+ "xalign", 0.5,
+ NULL);
+
+ g_signal_connect (view->priv->marks_renderer,
+ "activate",
+ G_CALLBACK (gutter_renderer_marks_activate),
view);
}
@@ -1656,9 +988,10 @@ gtk_source_view_init (GtkSourceView *view)
view->priv->right_margin_overlay_color = NULL;
view->priv->spaces_color = NULL;
- view->priv->mark_categories = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) mark_category_free);
+ view->priv->mark_categories = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
init_left_gutter (view);
@@ -1667,6 +1000,8 @@ gtk_source_view_init (GtkSourceView *view)
gtk_target_list_add_table (tl, drop_types, G_N_ELEMENTS (drop_types));
+ gtk_widget_set_has_tooltip (GTK_WIDGET (view), TRUE);
+
g_signal_connect (view,
"drag_data_received",
G_CALLBACK (view_dnd_drop),
@@ -1716,6 +1051,18 @@ gtk_source_view_dispose (GObject *object)
view->priv->completion = NULL;
}
+ if (view->priv->left_gutter)
+ {
+ g_object_unref (view->priv->left_gutter);
+ view->priv->left_gutter = NULL;
+ }
+
+ if (view->priv->right_gutter)
+ {
+ g_object_unref (view->priv->right_gutter);
+ view->priv->right_gutter = NULL;
+ }
+
G_OBJECT_CLASS (gtk_source_view_parent_class)->dispose (object);
}
@@ -1730,25 +1077,29 @@ gtk_source_view_finalize (GObject *object)
view = GTK_SOURCE_VIEW (object);
if (view->priv->style_scheme)
+ {
g_object_unref (view->priv->style_scheme);
+ }
if (view->priv->right_margin_line_color != NULL)
+ {
gdk_color_free (view->priv->right_margin_line_color);
+ }
if (view->priv->right_margin_overlay_color != NULL)
+ {
gdk_color_free (view->priv->right_margin_overlay_color);
+ }
if (view->priv->spaces_color != NULL)
+ {
gdk_color_free (view->priv->spaces_color);
+ }
if (view->priv->mark_categories)
+ {
g_hash_table_destroy (view->priv->mark_categories);
-
- if (view->priv->left_gutter)
- g_object_unref (view->priv->left_gutter);
-
- if (view->priv->right_gutter)
- g_object_unref (view->priv->right_gutter);
+ }
G_OBJECT_CLASS (gtk_source_view_parent_class)->finalize (object);
}
@@ -1855,6 +1206,7 @@ set_source_buffer (GtkSourceView *view,
g_signal_handlers_disconnect_by_func (view->priv->source_buffer,
buffer_style_scheme_changed_cb,
view);
+
g_object_unref (view->priv->source_buffer);
}
@@ -1884,7 +1236,9 @@ set_source_buffer (GtkSourceView *view,
* gtk_source_view_update_style_scheme(), that will check whether it's
* a GtkSourceBuffer or not */
if (buffer)
+ {
gtk_source_view_update_style_scheme (view);
+ }
}
static void
@@ -2462,7 +1816,7 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
cairo_t *cr)
{
GtkTextView *text_view;
- GdkRectangle clip;
+ GdkRectangle clip;
GArray *numbers;
GArray *pixels;
GArray *heights;
@@ -2471,8 +1825,10 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
gint i;
if (view->priv->source_buffer == NULL ||
- !gdk_cairo_get_clip_rectangle (cr, &clip))
+ !gdk_cairo_get_clip_rectangle (cr, &clip))
+ {
return;
+ }
text_view = GTK_TEXT_VIEW (view);
@@ -2481,18 +1837,18 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
/* 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_WINDOW_TEXT,
+ 0,
+ y1,
+ NULL,
+ &y1);
gtk_text_view_window_to_buffer_coords (text_view,
- GTK_TEXT_WINDOW_TEXT,
- 0,
- y2,
- NULL,
- &y2);
+ GTK_TEXT_WINDOW_TEXT,
+ 0,
+ y2,
+ NULL,
+ &y2);
numbers = g_array_new (FALSE, FALSE, sizeof (gint));
pixels = g_array_new (FALSE, FALSE, sizeof (gint));
@@ -2500,12 +1856,12 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
/* get the line numbers and y coordinates. */
gtk_source_view_get_lines (text_view,
- y1,
- y2,
- pixels,
- heights,
- numbers,
- &count);
+ y1,
+ y2,
+ pixels,
+ heights,
+ numbers,
+ &count);
if (count == 0)
{
@@ -2525,46 +1881,54 @@ gtk_source_view_paint_marks_background (GtkSourceView *view,
DEBUG ({
g_message ("Painting marks background for line numbers %d - %d",
- g_array_index (numbers, gint, 0),
- g_array_index (numbers, gint, count - 1));
+ 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;
+ 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);
+ line_to_paint,
+ NULL);
- background = NULL;
priority = -1;
while (marks != NULL)
{
- MarkCategory *cat = NULL;
+ GtkSourceMarkCategory *cat;
+ gint prio;
+ GdkColor bg;
- cat = gtk_source_view_get_mark_category (view, marks->data);
+ cat = gtk_source_view_get_mark_category (view,
+ gtk_source_mark_get_category (marks->data));
- if (cat != NULL && cat->background_set && cat->priority > priority)
+ prio = gtk_source_mark_category_get_priority (cat);
+
+ if (prio > priority &&
+ gtk_source_mark_category_get_background (cat, &bg))
{
- background = &cat->background;
- priority = cat->priority;
+ priority = prio;
+ background = bg;
}
marks = g_slist_delete_link (marks, marks);
}
- if (background != NULL)
- gtk_source_view_paint_line_background (text_view, cr,
- g_array_index (pixels, gint, i),
- g_array_index (heights, gint, i),
- background);
+ if (priority != -1)
+ {
+ gtk_source_view_paint_line_background (text_view,
+ cr,
+ g_array_index (pixels, gint, i),
+ g_array_index (heights, gint, i),
+ &background);
+ }
}
g_array_free (heights, TRUE);
@@ -3016,8 +2380,8 @@ gtk_source_view_draw (GtkWidget *widget,
window = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_TEXT);
- cairo_save (cr);
- gtk_cairo_transform_to_window (cr, widget, window);
+ cairo_save (cr);
+ gtk_cairo_transform_to_window (cr, widget, window);
event_handled = FALSE;
@@ -3079,19 +2443,21 @@ gtk_source_view_draw (GtkWidget *widget,
}
if (gtk_cairo_should_draw_window (cr, window))
+ {
gtk_source_view_paint_marks_background (view, cr);
+ }
/* Have GtkTextView draw the text first. */
if (GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw)
{
- /* Need to restore to original state here so the parent draw func
- * gets the correct context. */
+ /* Need to restore to original state here so the parent draw func
+ * gets the correct context. */
cairo_restore (cr);
cairo_save (cr);
event_handled =
- GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw (widget, cr);
+ GTK_WIDGET_CLASS (gtk_source_view_parent_class)->draw (widget, cr);
cairo_restore (cr);
@@ -3116,7 +2482,7 @@ gtk_source_view_draw (GtkWidget *widget,
g_print ("> gtk_source_view_draw end\n");
});
- cairo_restore (cr);
+ cairo_restore (cr);
return event_handled;
}
@@ -3231,10 +2597,8 @@ gtk_source_view_get_show_line_numbers (GtkSourceView *view)
**/
void
gtk_source_view_set_show_line_numbers (GtkSourceView *view,
- gboolean show)
+ gboolean show)
{
- GtkSourceGutter *gutter;
-
g_return_if_fail (view != NULL);
g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
@@ -3245,20 +2609,11 @@ gtk_source_view_set_show_line_numbers (GtkSourceView *view,
return;
}
- if (show)
- {
- gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, -1, -1);
- }
- else
- {
- gtk_cell_renderer_set_fixed_size (view->priv->line_renderer, 0, 0);
- }
+ gtk_source_gutter_renderer_set_visible (view->priv->line_renderer,
+ show);
view->priv->show_line_numbers = show;
- gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
- gtk_source_gutter_queue_draw (gutter);
-
g_object_notify (G_OBJECT (view), "show_line_numbers");
}
@@ -3293,8 +2648,6 @@ void
gtk_source_view_set_show_line_marks (GtkSourceView *view,
gboolean show)
{
- GtkSourceGutter *gutter;
-
g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
show = (show != FALSE);
@@ -3305,20 +2658,11 @@ gtk_source_view_set_show_line_marks (GtkSourceView *view,
}
- if (show)
- {
- gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, -1, -1);
- }
- else
- {
- gtk_cell_renderer_set_fixed_size (view->priv->marks_renderer, 0, 0);
- }
+ gtk_source_gutter_renderer_set_visible (view->priv->marks_renderer,
+ show);
view->priv->show_line_marks = show;
- gutter = gtk_source_view_get_gutter (view, GTK_TEXT_WINDOW_LEFT);
- gtk_source_gutter_queue_draw (gutter);
-
g_object_notify (G_OBJECT (view), "show_line_marks");
}
@@ -3435,446 +2779,6 @@ gtk_source_view_get_indent_width (GtkSourceView *view)
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)
-{
- MarkCategory *cat;
-
- cat = g_slice_new0 (MarkCategory);
- cat->priority = priority;
-
- return cat;
-}
-
-static void
-mark_category_free (MarkCategory *cat)
-{
- if (cat->tooltip_data_notify != NULL)
- {
- cat->tooltip_data_notify (cat->tooltip_data);
- }
-
- if (cat->icon_pixbuf)
- {
- g_object_unref (cat->icon_pixbuf);
- }
-
- if (cat->cached_icon)
- {
- g_object_unref (cat->cached_icon);
- }
-
- g_free (cat->icon_stock);
- g_free (cat->icon_name);
-
- g_slice_free (MarkCategory, cat);
-}
-
-static MarkCategory *
-gtk_source_view_get_mark_category (GtkSourceView *view,
- GtkSourceMark *mark)
-{
- const gchar *category;
- category = gtk_source_mark_get_category (mark);
- if (category)
- return g_hash_table_lookup (view->priv->mark_categories,
- category);
- else
- return NULL;
-}
-
-static MarkCategory *
-gtk_source_view_ensure_category (GtkSourceView *view,
- const gchar *name)
-{
- MarkCategory *cat;
-
- cat = g_hash_table_lookup (view->priv->mark_categories, name);
-
- if (cat == NULL)
- {
- cat = mark_category_new (0);
- g_hash_table_insert (view->priv->mark_categories,
- g_strdup (name),
- cat);
- }
-
- return cat;
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_pixbuf:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @pixbuf: (allow-none): a #GdkPixbuf, or %NULL.
- *
- * Sets the icon to be used for @category to @pixbuf.
- * If @pixbuf is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_pixbuf (GtkSourceView *view,
- const gchar *category,
- GdkPixbuf *pixbuf)
-{
- MarkCategory *cat;
-
- g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
- g_return_if_fail (category != NULL);
- g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
-
- cat = gtk_source_view_ensure_category (view, category);
-
- if (cat->icon_pixbuf != NULL)
- {
- g_object_unref (cat->icon_pixbuf);
- cat->icon_pixbuf = NULL;
- }
-
- remove_cached_category_icon (cat);
-
- if (pixbuf != NULL)
- {
- cat->icon_pixbuf = g_object_ref (pixbuf);
- }
-
- cat->icon_type = ICON_TYPE_PIXBUF;
-
- /* We may need to redraw the margin now */
- gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_icon_name:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @name: (allow-none): the themed icon name, or %NULL.
- *
- * Sets the icon to be used for @category to the named theme item @name.
- * If @name is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_icon_name (GtkSourceView *view,
- const gchar *category,
- const gchar *name)
-{
- MarkCategory *cat;
-
- g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
- g_return_if_fail (category != NULL);
-
- cat = gtk_source_view_ensure_category (view, category);
-
- if (cat->icon_name != NULL)
- {
- g_free (cat->icon_name);
- cat->icon_name = NULL;
- }
-
- remove_cached_category_icon (cat);
-
- if (name != NULL)
- {
- cat->icon_name = g_strdup (name);
- }
-
- cat->icon_type = ICON_TYPE_NAME;
-
- /* We may need to redraw the margin now */
- gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_set_mark_category_icon_from_stock:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @stock_id: (allow-none): the stock id, or %NULL.
- *
- * Sets the icon to be used for @category to the stock item @stock_id.
- * If @stock_id is %NULL, the icon is unset.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_icon_from_stock (GtkSourceView *view,
- const gchar *category,
- const gchar *stock_id)
-{
- MarkCategory *cat;
-
- g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
- g_return_if_fail (category != NULL);
-
- cat = gtk_source_view_ensure_category (view, category);
-
- if (cat->icon_stock != NULL)
- {
- g_free (cat->icon_stock);
- cat->icon_stock = NULL;
- }
-
- remove_cached_category_icon (cat);
-
- if (stock_id != NULL)
- {
- cat->icon_stock = g_strdup (stock_id);
- }
-
- cat->icon_type = ICON_TYPE_STOCK;
-
- /* We may need to redraw the margin now */
- gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-static void
-set_mark_category_tooltip_func (GtkSourceView *view,
- const gchar *category,
- GtkSourceViewMarkTooltipFunc func,
- gpointer user_data,
- GDestroyNotify user_data_notify,
- gboolean markup)
-{
- GtkWidget *widget;
- MarkCategory *cat;
-
- g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
- g_return_if_fail (category != NULL);
-
- widget = GTK_WIDGET (view);
- cat = gtk_source_view_ensure_category (view, category);
-
- if (cat->tooltip_data_notify)
- cat->tooltip_data_notify (cat->tooltip_data);
-
- cat->tooltip_func = func;
- cat->tooltip_markup = markup;
- cat->tooltip_data = user_data;
- cat->tooltip_data_notify = user_data_notify;
-
- if (func != NULL)
- {
- gtk_widget_set_has_tooltip (widget, TRUE);
- if (gtk_widget_get_realized (widget))
- {
- gtk_widget_trigger_tooltip_query (widget);
- }
- }
-}
-
-/**
- * gtk_source_view_set_mark_category_tooltip_func:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @func: (allow-none): a #GtkSourceViewMarkTooltipFunc or %NULL.
- * @user_data: (allow-none): user data which will be passed to @func.
- * @user_data_notify: (allow-none):a function to free the memory allocated
- * for @user_data or %NULL if you do not want to supply such a function.
- *
- * Set a #GtkSourceViewMarkTooltipFunc used to set tooltip on marks from the
- * given mark @category.
- * If you also specified a function with
- * gtk_source_view_set_mark_category_tooltip_markup_func() the markup
- * variant takes precedence.
- *
- * <informalexample><programlisting><![CDATA[
- * static gchar *
- * tooltip_func (GtkSourceMark *mark,
- * gpointer user_data)
- * {
- * gchar *text;
- *
- * text = get_tooltip_for_mark (mark, user_data);
- *
- * return text;
- * }
- *
- * ...
- *
- * GtkSourceView *view;
- *
- * gtk_source_view_set_mark_category_tooltip_func (view, "other-mark",
- * tooltip_func,
- * NULL, NULL);
- * ]]></programlisting></informalexample>
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_tooltip_func (GtkSourceView *view,
- const gchar *category,
- GtkSourceViewMarkTooltipFunc func,
- gpointer user_data,
- GDestroyNotify user_data_notify)
-{
- set_mark_category_tooltip_func (view, category, func, user_data,
- user_data_notify, FALSE);
-}
-
-/**
- * gtk_source_view_set_mark_category_tooltip_markup_func:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @markup_func: (allow-none): a #GtkSourceViewMarkTooltipFunc or %NULL.
- * @user_data: (allow-none): user data which will be passed to @func.
- * @user_data_notify: (allow-none):a function to free the memory allocated
- * for @user_data or %NULL if you do not want to supply such a function.
- *
- * See gtk_source_view_set_mark_category_tooltip_func() for more information.
- *
- * Since: 2.8
- */
-void
-gtk_source_view_set_mark_category_tooltip_markup_func (GtkSourceView *view,
- const gchar *category,
- GtkSourceViewMarkTooltipFunc markup_func,
- gpointer user_data,
- GDestroyNotify user_data_notify)
-{
- set_mark_category_tooltip_func (view, category, markup_func, user_data,
- user_data_notify, TRUE);
-}
-
-/**
- * gtk_source_view_set_mark_category_background:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- * @color: (allow-none): 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 = gtk_source_view_ensure_category (view, category);
- 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.
- * @priority: the priority for the category
- *
- * Set the @priority for the given mark @category. When there are
- * multiple marks on the same line, marks of categories with
- * higher priorities will be drawn on top.
- *
- * Since: 2.2
- */
-void
-gtk_source_view_set_mark_category_priority (GtkSourceView *view,
- const gchar *category,
- gint priority)
-{
- MarkCategory *cat;
-
- g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
- g_return_if_fail (category != NULL);
-
- cat = gtk_source_view_ensure_category (view, category);
- cat->priority = priority;
-
- /* We may need to redraw now, if the priorities affect appearance */
- gtk_widget_queue_draw (GTK_WIDGET (view));
-}
-
-/**
- * gtk_source_view_get_mark_category_priority:
- * @view: a #GtkSourceView.
- * @category: a mark category.
- *
- * Gets the priority which is associated with the given @category.
- *
- * Return value: the priority or if @category
- * exists but no priority was set, it defaults to 0.
- *
- * Since: 2.2
- */
-gint
-gtk_source_view_get_mark_category_priority (GtkSourceView *view,
- const gchar *category)
-{
- MarkCategory *cat;
-
- g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), 0);
- g_return_val_if_fail (category != NULL, 0);
-
- cat = g_hash_table_lookup (view->priv->mark_categories, category);
- if (cat != NULL)
- return cat->priority;
- else
- {
- g_warning ("Marker Category %s does not exist!", category);
- return 0;
- }
-}
-
static gchar *
compute_indentation (GtkSourceView *view,
GtkTextIter *cur)
@@ -5302,3 +4206,38 @@ gtk_source_view_get_gutter (GtkSourceView *view,
return view->priv->right_gutter;
}
}
+
+/**
+ * gtk_source_view_get_mark_category:
+ * @view: a #GtkSourceView
+ * @category: the category
+ *
+ * Get the source mark category object for @category. A
+ * #GtkSourceMarkCategory is automatically created for the given category
+ * if it does not exist yet.
+ *
+ * Returns: (transfer none): the #GtkSourceMarkCategory object
+ *
+ */
+GtkSourceMarkCategory *
+gtk_source_view_get_mark_category (GtkSourceView *view,
+ const gchar *category)
+{
+ GtkSourceMarkCategory *ret;
+
+ g_return_val_if_fail (GTK_IS_SOURCE_VIEW (view), NULL);
+ g_return_val_if_fail (category != NULL, NULL);
+
+ ret = g_hash_table_lookup (view->priv->mark_categories, category);
+
+ if (!ret)
+ {
+ ret = gtk_source_mark_category_new (category);
+
+ g_hash_table_insert (view->priv->mark_categories,
+ g_strdup (category),
+ ret);
+ }
+
+ return ret;
+}
diff --git a/gtksourceview/gtksourceview.h b/gtksourceview/gtksourceview.h
index 2e3b87c..57a1da2 100644
--- a/gtksourceview/gtksourceview.h
+++ b/gtksourceview/gtksourceview.h
@@ -29,6 +29,7 @@
#include <gtksourceview/gtksourcebuffer.h>
#include <gtksourceview/gtksourcecompletion.h>
#include <gtksourceview/gtksourcegutter.h>
+#include <gtksourceview/gtksourcemarkcategory.h>
G_BEGIN_DECLS
@@ -192,60 +193,9 @@ void gtk_source_view_set_show_line_marks (GtkSourceView *view,
gboolean show);
gboolean gtk_source_view_get_show_line_marks (GtkSourceView *view);
-void gtk_source_view_set_mark_category_icon_from_pixbuf
- (GtkSourceView *view,
- const gchar *category,
- GdkPixbuf *pixbuf);
-
-void gtk_source_view_set_mark_category_icon_from_stock
- (GtkSourceView *view,
- const gchar *category,
- const gchar *stock_id);
-
-void gtk_source_view_set_mark_category_icon_from_icon_name
- (GtkSourceView *view,
- const gchar *category,
- const gchar *name);
-
-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);
-
-/**
- * GtkSourceViewMarkTooltipFunc:
- * @mark: the #GtkSourceMark
- * @user_data: user data pointer which was passed to gtk_source_view_set_mark_category_tooltip_func()
- *
- * Function type for setting up a tooltip for #GtkSourceMark.
- * Returns: a newly-allocated string that is going to be shown as tooltip text.
- */
-typedef gchar * (*GtkSourceViewMarkTooltipFunc) (GtkSourceMark *mark,
- gpointer user_data);
-void gtk_source_view_set_mark_category_tooltip_func
- (GtkSourceView *view,
- const gchar *category,
- GtkSourceViewMarkTooltipFunc func,
- gpointer user_data,
- GDestroyNotify user_data_notify);
-void gtk_source_view_set_mark_category_tooltip_markup_func
- (GtkSourceView *view,
- const gchar *category,
- GtkSourceViewMarkTooltipFunc markup_func,
- gpointer user_data,
- GDestroyNotify user_data_notify);
-
-void gtk_source_view_set_mark_category_priority
- (GtkSourceView *view,
- const gchar *category,
- gint priority);
-gint gtk_source_view_get_mark_category_priority
- (GtkSourceView *view,
- const gchar *category);
+GtkSourceMarkCategory *
+ gtk_source_view_get_mark_category (GtkSourceView *view,
+ const gchar *category);
void gtk_source_view_set_smart_home_end (GtkSourceView *view,
GtkSourceSmartHomeEndType smart_he);
diff --git a/tests/test-widget.c b/tests/test-widget.c
index 43709ec..0511edc 100644
--- a/tests/test-widget.c
+++ b/tests/test-widget.c
@@ -1217,9 +1217,13 @@ line_mark_activated (GtkSourceGutter *gutter,
const gchar *mark_type;
if (ev->button == 1)
+ {
mark_type = MARK_TYPE_1;
+ }
else
+ {
mark_type = MARK_TYPE_2;
+ }
buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
@@ -1276,49 +1280,61 @@ bracket_matched (GtkSourceBuffer *buffer G_GNUC_UNUSED,
/* Window creation functions -------------------------------------------------------- */
static gchar *
-mark_tooltip_func (GtkSourceMark *mark,
- gpointer user_data)
+mark_tooltip_func (GtkSourceMarkCategory *category,
+ GtkSourceMark *mark,
+ GtkSourceView *view)
{
GtkTextBuffer *buf;
GtkTextIter iter;
gint line, column;
-
+
buf = gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark));
-
+
gtk_text_buffer_get_iter_at_mark (buf, &iter, GTK_TEXT_MARK (mark));
line = gtk_text_iter_get_line (&iter) + 1;
column = gtk_text_iter_get_line_offset (&iter);
- if (strcmp (gtk_source_mark_get_category (mark), MARK_TYPE_1) == 0)
+ if (g_strcmp0 (gtk_source_mark_category_get_id (category), MARK_TYPE_1) == 0)
+ {
return g_strdup_printf ("Line: %d, Column: %d", line, column);
+ }
else
+ {
return g_strdup_printf ("<b>Line</b>: %d\n<i>Column</i>: %d", line, column);
+ }
}
static void
add_source_mark_pixbufs (GtkSourceView *view)
{
GdkColor color;
+ GtkSourceMarkCategory *cat;
gdk_color_parse ("lightgreen", &color);
- gtk_source_view_set_mark_category_background (view, MARK_TYPE_1, &color);
- gtk_source_view_set_mark_category_icon_from_stock (view, MARK_TYPE_1, GTK_STOCK_YES);
- gtk_source_view_set_mark_category_priority (view, MARK_TYPE_1, 1);
- gtk_source_view_set_mark_category_tooltip_func (view,
- MARK_TYPE_1,
- mark_tooltip_func,
- NULL,
- NULL);
+
+ cat = gtk_source_view_get_mark_category (view, MARK_TYPE_1);
+
+ gtk_source_mark_category_set_background (cat, &color);
+ gtk_source_mark_category_set_stock_id (cat, GTK_STOCK_YES);
+ gtk_source_mark_category_set_priority (cat, 1);
+
+ g_signal_connect (cat,
+ "query-tooltip-markup",
+ G_CALLBACK (mark_tooltip_func),
+ view);
gdk_color_parse ("pink", &color);
- gtk_source_view_set_mark_category_background (view, MARK_TYPE_2, &color);
- gtk_source_view_set_mark_category_icon_from_stock (view, MARK_TYPE_2, GTK_STOCK_NO);
- gtk_source_view_set_mark_category_priority (view, MARK_TYPE_2, 2);
- gtk_source_view_set_mark_category_tooltip_markup_func (view,
- MARK_TYPE_2,
- mark_tooltip_func,
- NULL,
- NULL);
+
+ cat = gtk_source_view_get_mark_category (view, MARK_TYPE_2);
+
+ gtk_source_mark_category_set_background (cat, &color);
+ gtk_source_mark_category_set_stock_id (cat, GTK_STOCK_NO);
+ gtk_source_mark_category_set_priority (cat, 2);
+
+ g_signal_connect (cat,
+ "query-tooltip-markup",
+ G_CALLBACK (mark_tooltip_func),
+ view);
}
static GtkWidget *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]