Blame gtksourceview/gtksourcegutter.c

Packit a7d494
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- /
Packit a7d494
 * gtksourcegutter.c
Packit a7d494
 * This file is part of GtkSourceView
Packit a7d494
 *
Packit a7d494
 * Copyright (C) 2009 - Jesse van den Kieboom
Packit a7d494
 *
Packit a7d494
 * GtkSourceView is free software; you can redistribute it and/or
Packit a7d494
 * modify it under the terms of the GNU Lesser General Public
Packit a7d494
 * License as published by the Free Software Foundation; either
Packit a7d494
 * version 2.1 of the License, or (at your option) any later version.
Packit a7d494
 *
Packit a7d494
 * GtkSourceView is distributed in the hope that it will be useful,
Packit a7d494
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a7d494
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a7d494
 * Lesser General Public License for more details.
Packit a7d494
 *
Packit a7d494
 * You should have received a copy of the GNU Lesser General Public
Packit a7d494
 * License along with this library; if not, write to the Free Software
Packit a7d494
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit a7d494
 */
Packit a7d494
Packit a7d494
#ifdef HAVE_CONFIG_H
Packit a7d494
#include <config.h>
Packit a7d494
#endif
Packit a7d494
Packit a7d494
#include "gtksourcegutter.h"
Packit a7d494
#include "gtksourcegutter-private.h"
Packit a7d494
#include "gtksourceview.h"
Packit a7d494
#include "gtksourceview-i18n.h"
Packit a7d494
#include "gtksourcegutterrenderer.h"
Packit a7d494
#include "gtksourcegutterrenderer-private.h"
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * SECTION:gutter
Packit a7d494
 * @Short_description: Gutter object for GtkSourceView
Packit a7d494
 * @Title: GtkSourceGutter
Packit a7d494
 * @See_also: #GtkSourceView, #GtkSourceMark
Packit a7d494
 *
Packit a7d494
 * The #GtkSourceGutter object represents the left or right gutter of the text
Packit a7d494
 * view. It is used by #GtkSourceView to draw the line numbers and
Packit a7d494
 * #GtkSourceMarks that might be present on a line. By packing
Packit a7d494
 * additional #GtkSourceGutterRenderer objects in the gutter, you can extend the
Packit a7d494
 * gutter with your own custom drawings.
Packit a7d494
 *
Packit a7d494
 * To get a #GtkSourceGutter, use the gtk_source_view_get_gutter() function.
Packit a7d494
 *
Packit a7d494
 * The gutter works very much the same way as cells rendered in a #GtkTreeView.
Packit a7d494
 * The concept is similar, with the exception that the gutter does not have an
Packit a7d494
 * underlying #GtkTreeModel. The builtin line number renderer is at position
Packit a7d494
 * #GTK_SOURCE_VIEW_GUTTER_POSITION_LINES (-30) and the marks renderer is at
Packit a7d494
 * #GTK_SOURCE_VIEW_GUTTER_POSITION_MARKS (-20). The gutter sorts the renderers
Packit a7d494
 * in ascending order, from left to right. So the marks are displayed on the
Packit a7d494
 * right of the line numbers.
Packit a7d494
 */
Packit a7d494
Packit a7d494
enum
Packit a7d494
{
Packit a7d494
	PROP_0,
Packit a7d494
	PROP_VIEW,
Packit a7d494
	PROP_WINDOW_TYPE,
Packit a7d494
	PROP_XPAD,
Packit a7d494
	PROP_YPAD
Packit a7d494
};
Packit a7d494
Packit a7d494
typedef struct
Packit a7d494
{
Packit a7d494
	GtkSourceGutterRenderer *renderer;
Packit a7d494
Packit a7d494
	gint prelit;
Packit a7d494
	gint position;
Packit a7d494
Packit a7d494
	gulong queue_draw_handler;
Packit a7d494
	gulong size_changed_handler;
Packit a7d494
	gulong notify_xpad_handler;
Packit a7d494
	gulong notify_ypad_handler;
Packit a7d494
	gulong notify_visible_handler;
Packit a7d494
} Renderer;
Packit a7d494
Packit a7d494
struct _GtkSourceGutterPrivate
Packit a7d494
{
Packit a7d494
	GtkSourceView *view;
Packit a7d494
	GtkTextWindowType window_type;
Packit a7d494
	GtkOrientation orientation;
Packit a7d494
Packit a7d494
	GList *renderers;
Packit a7d494
Packit a7d494
	gint xpad;
Packit a7d494
	gint ypad;
Packit a7d494
Packit a7d494
	guint is_drawing : 1;
Packit a7d494
};
Packit a7d494
Packit a7d494
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceGutter, gtk_source_gutter, G_TYPE_OBJECT)
Packit a7d494
Packit a7d494
static gboolean on_view_motion_notify_event (GtkSourceView   *view,
Packit a7d494
                                             GdkEventMotion  *event,
Packit a7d494
                                             GtkSourceGutter *gutter);
Packit a7d494
Packit a7d494
Packit a7d494
static gboolean on_view_enter_notify_event (GtkSourceView    *view,
Packit a7d494
                                            GdkEventCrossing *event,
Packit a7d494
                                            GtkSourceGutter  *gutter);
Packit a7d494
Packit a7d494
static gboolean on_view_leave_notify_event (GtkSourceView    *view,
Packit a7d494
                                            GdkEventCrossing *event,
Packit a7d494
                                            GtkSourceGutter  *gutter);
Packit a7d494
Packit a7d494
static gboolean on_view_button_press_event (GtkSourceView    *view,
Packit a7d494
                                            GdkEventButton   *event,
Packit a7d494
                                            GtkSourceGutter  *gutter);
Packit a7d494
Packit a7d494
static gboolean on_view_query_tooltip (GtkSourceView   *view,
Packit a7d494
                                       gint             x,
Packit a7d494
                                       gint             y,
Packit a7d494
                                       gboolean         keyboard_mode,
Packit a7d494
                                       GtkTooltip      *tooltip,
Packit a7d494
                                       GtkSourceGutter *gutter);
Packit a7d494
Packit a7d494
static void on_view_style_updated (GtkSourceView    *view,
Packit a7d494
                                   GtkSourceGutter  *gutter);
Packit a7d494
Packit a7d494
static void do_redraw (GtkSourceGutter *gutter);
Packit a7d494
static void update_gutter_size (GtkSourceGutter *gutter);
Packit a7d494
Packit a7d494
static GdkWindow *
Packit a7d494
get_window (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	return gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                 gutter->priv->window_type);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_renderer_size_changed (GtkSourceGutterRenderer *renderer,
Packit a7d494
                          GParamSpec              *spec,
Packit a7d494
                          GtkSourceGutter         *gutter)
Packit a7d494
{
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_renderer_queue_draw (GtkSourceGutterRenderer *renderer,
Packit a7d494
                        GtkSourceGutter         *gutter)
Packit a7d494
{
Packit a7d494
	do_redraw (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_renderer_notify_padding (GtkSourceGutterRenderer *renderer,
Packit a7d494
                            GParamSpec              *spec,
Packit a7d494
                            GtkSourceGutter         *gutter)
Packit a7d494
{
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_renderer_notify_visible (GtkSourceGutterRenderer *renderer,
Packit a7d494
                            GParamSpec              *spec,
Packit a7d494
                            GtkSourceGutter         *gutter)
Packit a7d494
{
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
static Renderer *
Packit a7d494
renderer_new (GtkSourceGutter         *gutter,
Packit a7d494
              GtkSourceGutterRenderer *renderer,
Packit a7d494
              gint                     position)
Packit a7d494
{
Packit a7d494
	Renderer *ret = g_slice_new0 (Renderer);
Packit a7d494
Packit a7d494
	ret->renderer = g_object_ref_sink (renderer);
Packit a7d494
	ret->position = position;
Packit a7d494
	ret->prelit = -1;
Packit a7d494
Packit a7d494
	_gtk_source_gutter_renderer_set_view (renderer,
Packit a7d494
	                                      GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                      gutter->priv->window_type);
Packit a7d494
Packit a7d494
	ret->size_changed_handler =
Packit a7d494
		g_signal_connect (ret->renderer,
Packit a7d494
		                  "notify::size",
Packit a7d494
		                  G_CALLBACK (on_renderer_size_changed),
Packit a7d494
		                  gutter);
Packit a7d494
Packit a7d494
	ret->queue_draw_handler =
Packit a7d494
		g_signal_connect (ret->renderer,
Packit a7d494
		                  "queue-draw",
Packit a7d494
		                  G_CALLBACK (on_renderer_queue_draw),
Packit a7d494
		                  gutter);
Packit a7d494
Packit a7d494
	ret->notify_xpad_handler =
Packit a7d494
		g_signal_connect (ret->renderer,
Packit a7d494
		                  "notify::xpad",
Packit a7d494
		                  G_CALLBACK (on_renderer_notify_padding),
Packit a7d494
		                  gutter);
Packit a7d494
Packit a7d494
	ret->notify_ypad_handler =
Packit a7d494
		g_signal_connect (ret->renderer,
Packit a7d494
		                  "notify::ypad",
Packit a7d494
		                  G_CALLBACK (on_renderer_notify_padding),
Packit a7d494
		                  gutter);
Packit a7d494
Packit a7d494
	ret->notify_visible_handler =
Packit a7d494
		g_signal_connect (ret->renderer,
Packit a7d494
		                  "notify::visible",
Packit a7d494
		                  G_CALLBACK (on_renderer_notify_visible),
Packit a7d494
		                  gutter);
Packit a7d494
Packit a7d494
	return ret;
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
renderer_free (Renderer *renderer)
Packit a7d494
{
Packit a7d494
	g_signal_handler_disconnect (renderer->renderer,
Packit a7d494
	                             renderer->queue_draw_handler);
Packit a7d494
Packit a7d494
	g_signal_handler_disconnect (renderer->renderer,
Packit a7d494
	                             renderer->size_changed_handler);
Packit a7d494
Packit a7d494
	g_signal_handler_disconnect (renderer->renderer,
Packit a7d494
	                             renderer->notify_xpad_handler);
Packit a7d494
Packit a7d494
	g_signal_handler_disconnect (renderer->renderer,
Packit a7d494
	                             renderer->notify_ypad_handler);
Packit a7d494
Packit a7d494
	g_signal_handler_disconnect (renderer->renderer,
Packit a7d494
	                             renderer->notify_visible_handler);
Packit a7d494
Packit a7d494
	_gtk_source_gutter_renderer_set_view (renderer->renderer,
Packit a7d494
	                                      NULL,
Packit a7d494
	                                      GTK_TEXT_WINDOW_PRIVATE);
Packit a7d494
Packit a7d494
	g_object_unref (renderer->renderer);
Packit a7d494
	g_slice_free (Renderer, renderer);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_dispose (GObject *object)
Packit a7d494
{
Packit a7d494
	GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (object);
Packit a7d494
Packit a7d494
	g_list_free_full (gutter->priv->renderers, (GDestroyNotify)renderer_free);
Packit a7d494
	gutter->priv->renderers = NULL;
Packit a7d494
Packit a7d494
	gutter->priv->view = NULL;
Packit a7d494
Packit a7d494
	G_OBJECT_CLASS (gtk_source_gutter_parent_class)->dispose (object);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_get_property (GObject    *object,
Packit a7d494
                                guint       prop_id,
Packit a7d494
                                GValue     *value,
Packit a7d494
                                GParamSpec *pspec)
Packit a7d494
{
Packit a7d494
	GtkSourceGutter *self = GTK_SOURCE_GUTTER (object);
Packit a7d494
Packit a7d494
	switch (prop_id)
Packit a7d494
	{
Packit a7d494
		case PROP_VIEW:
Packit a7d494
			g_value_set_object (value, self->priv->view);
Packit a7d494
			break;
Packit a7d494
		case PROP_WINDOW_TYPE:
Packit a7d494
			g_value_set_enum (value, self->priv->window_type);
Packit a7d494
			break;
Packit a7d494
		case PROP_XPAD:
Packit a7d494
			g_value_set_int (value, self->priv->xpad);
Packit a7d494
			break;
Packit a7d494
		case PROP_YPAD:
Packit a7d494
			g_value_set_int (value, self->priv->ypad);
Packit a7d494
			break;
Packit a7d494
		default:
Packit a7d494
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_view_realize (GtkSourceView   *view,
Packit a7d494
                 GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
set_view (GtkSourceGutter *gutter,
Packit a7d494
          GtkSourceView   *view)
Packit a7d494
{
Packit a7d494
	gutter->priv->view = view;
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "motion-notify-event",
Packit a7d494
				 G_CALLBACK (on_view_motion_notify_event),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "enter-notify-event",
Packit a7d494
				 G_CALLBACK (on_view_enter_notify_event),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "leave-notify-event",
Packit a7d494
				 G_CALLBACK (on_view_leave_notify_event),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "button-press-event",
Packit a7d494
				 G_CALLBACK (on_view_button_press_event),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "query-tooltip",
Packit a7d494
				 G_CALLBACK (on_view_query_tooltip),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "realize",
Packit a7d494
				 G_CALLBACK (on_view_realize),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
Packit a7d494
	g_signal_connect_object (view,
Packit a7d494
				 "style-updated",
Packit a7d494
				 G_CALLBACK (on_view_style_updated),
Packit a7d494
				 gutter,
Packit a7d494
				 0);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
do_redraw (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	GdkWindow *window;
Packit a7d494
Packit a7d494
	window = gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                   gutter->priv->window_type);
Packit a7d494
Packit a7d494
	if (window && !gutter->priv->is_drawing)
Packit a7d494
	{
Packit a7d494
		gdk_window_invalidate_rect (window, NULL, FALSE);
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static gint
Packit a7d494
calculate_gutter_size (GtkSourceGutter *gutter,
Packit a7d494
		       GArray          *sizes)
Packit a7d494
{
Packit a7d494
	GList *item;
Packit a7d494
	gint total_width = 0;
Packit a7d494
Packit a7d494
	/* Calculate size */
Packit a7d494
	for (item = gutter->priv->renderers; item; item = g_list_next (item))
Packit a7d494
	{
Packit a7d494
		Renderer *renderer = item->data;
Packit a7d494
		gint width;
Packit a7d494
Packit a7d494
		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
		{
Packit a7d494
			width = 0;
Packit a7d494
		}
Packit a7d494
		else
Packit a7d494
		{
Packit a7d494
			gint xpad;
Packit a7d494
			gint size;
Packit a7d494
Packit a7d494
			size = gtk_source_gutter_renderer_get_size (renderer->renderer);
Packit a7d494
Packit a7d494
			gtk_source_gutter_renderer_get_padding (renderer->renderer,
Packit a7d494
			                                        &xpad,
Packit a7d494
			                                        NULL);
Packit a7d494
Packit a7d494
			width = size + 2 * xpad;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		if (sizes)
Packit a7d494
		{
Packit a7d494
			g_array_append_val (sizes, width);
Packit a7d494
		}
Packit a7d494
Packit a7d494
		total_width += width;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return total_width;
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
update_gutter_size (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	gint width = calculate_gutter_size (gutter, NULL);
Packit a7d494
Packit a7d494
	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                      gutter->priv->window_type,
Packit a7d494
	                                      width);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
set_padding (GtkSourceGutter *gutter,
Packit a7d494
             gint            *field,
Packit a7d494
             gint             padding,
Packit a7d494
             const gchar     *name,
Packit a7d494
             gboolean         resize)
Packit a7d494
{
Packit a7d494
	if (*field == padding || padding < 0)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	*field = padding;
Packit a7d494
Packit a7d494
	g_object_notify (G_OBJECT (gutter), name);
Packit a7d494
Packit a7d494
	if (resize)
Packit a7d494
	{
Packit a7d494
		update_gutter_size (gutter);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return TRUE;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
set_xpad (GtkSourceGutter *gutter,
Packit a7d494
          gint             xpad,
Packit a7d494
          gboolean         resize)
Packit a7d494
{
Packit a7d494
	return set_padding (gutter, &gutter->priv->xpad, xpad, "xpad", resize);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
set_ypad (GtkSourceGutter *gutter,
Packit a7d494
          gint             ypad,
Packit a7d494
          gboolean         resize)
Packit a7d494
{
Packit a7d494
	return set_padding (gutter, &gutter->priv->ypad, ypad, "ypad", resize);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_set_property (GObject       *object,
Packit a7d494
                                guint          prop_id,
Packit a7d494
                                const GValue  *value,
Packit a7d494
                                GParamSpec    *pspec)
Packit a7d494
{
Packit a7d494
	GtkSourceGutter *self = GTK_SOURCE_GUTTER (object);
Packit a7d494
Packit a7d494
	switch (prop_id)
Packit a7d494
	{
Packit a7d494
		case PROP_VIEW:
Packit a7d494
			set_view (self, GTK_SOURCE_VIEW (g_value_get_object (value)));
Packit a7d494
			break;
Packit a7d494
		case PROP_WINDOW_TYPE:
Packit a7d494
			self->priv->window_type = g_value_get_enum (value);
Packit a7d494
			break;
Packit a7d494
		case PROP_XPAD:
Packit a7d494
			set_xpad (self, g_value_get_int (value), TRUE);
Packit a7d494
			break;
Packit a7d494
		case PROP_YPAD:
Packit a7d494
			set_ypad (self, g_value_get_int (value), TRUE);
Packit a7d494
			break;
Packit a7d494
		default:
Packit a7d494
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit a7d494
			break;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_constructed (GObject *object)
Packit a7d494
{
Packit a7d494
	GtkSourceGutter *gutter;
Packit a7d494
Packit a7d494
	gutter = GTK_SOURCE_GUTTER (object);
Packit a7d494
Packit a7d494
	if (gutter->priv->window_type == GTK_TEXT_WINDOW_LEFT ||
Packit a7d494
	    gutter->priv->window_type == GTK_TEXT_WINDOW_RIGHT)
Packit a7d494
	{
Packit a7d494
		gutter->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
Packit a7d494
	}
Packit a7d494
	else
Packit a7d494
	{
Packit a7d494
		gutter->priv->orientation = GTK_ORIENTATION_VERTICAL;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	G_OBJECT_CLASS (gtk_source_gutter_parent_class)->constructed (object);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
Packit a7d494
{
Packit a7d494
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit a7d494
Packit a7d494
	object_class->set_property = gtk_source_gutter_set_property;
Packit a7d494
	object_class->get_property = gtk_source_gutter_get_property;
Packit a7d494
Packit a7d494
	object_class->dispose = gtk_source_gutter_dispose;
Packit a7d494
	object_class->constructed = gtk_source_gutter_constructed;
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceGutter:view:
Packit a7d494
	 *
Packit a7d494
	 * The #GtkSourceView of the gutter.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (object_class,
Packit a7d494
	                                 PROP_VIEW,
Packit a7d494
	                                 g_param_spec_object ("view",
Packit a7d494
	                                                      "View",
Packit a7d494
	                                                      "",
Packit a7d494
	                                                      GTK_SOURCE_TYPE_VIEW,
Packit a7d494
	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceGutter:window-type:
Packit a7d494
	 *
Packit a7d494
	 * The text window type on which the window is placed.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (object_class,
Packit a7d494
	                                 PROP_WINDOW_TYPE,
Packit a7d494
	                                 g_param_spec_enum ("window_type",
Packit a7d494
	                                                    "Window Type",
Packit a7d494
	                                                    "The gutters' text window type",
Packit a7d494
	                                                    GTK_TYPE_TEXT_WINDOW_TYPE,
Packit a7d494
	                                                    0,
Packit a7d494
	                                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceGutter:xpad:
Packit a7d494
	 *
Packit a7d494
	 * The x-padding.
Packit a7d494
	 *
Packit a7d494
	 * Deprecated: 3.12: Use the #GtkSourceGutterRenderer's
Packit a7d494
	 * #GtkSourceGutterRenderer:xpad property instead.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (object_class,
Packit a7d494
	                                 PROP_XPAD,
Packit a7d494
	                                 g_param_spec_int ("xpad",
Packit a7d494
	                                                   "X Padding",
Packit a7d494
	                                                   "The x-padding",
Packit a7d494
	                                                   -1,
Packit a7d494
	                                                   G_MAXINT,
Packit a7d494
	                                                   0,
Packit a7d494
	                                                   G_PARAM_READWRITE |
Packit a7d494
							   G_PARAM_CONSTRUCT |
Packit a7d494
							   G_PARAM_DEPRECATED));
Packit a7d494
Packit a7d494
	/**
Packit a7d494
	 * GtkSourceGutter:ypad:
Packit a7d494
	 *
Packit a7d494
	 * The y-padding.
Packit a7d494
	 *
Packit a7d494
	 * Deprecated: 3.12: Use the #GtkSourceGutterRenderer's
Packit a7d494
	 * #GtkSourceGutterRenderer:ypad property instead.
Packit a7d494
	 */
Packit a7d494
	g_object_class_install_property (object_class,
Packit a7d494
	                                 PROP_YPAD,
Packit a7d494
	                                 g_param_spec_int ("ypad",
Packit a7d494
	                                                   "Y Padding",
Packit a7d494
	                                                   "The y-padding",
Packit a7d494
	                                                   -1,
Packit a7d494
	                                                   G_MAXINT,
Packit a7d494
	                                                   0,
Packit a7d494
	                                                   G_PARAM_READWRITE |
Packit a7d494
							   G_PARAM_CONSTRUCT |
Packit a7d494
							   G_PARAM_DEPRECATED));
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
gtk_source_gutter_init (GtkSourceGutter *self)
Packit a7d494
{
Packit a7d494
	self->priv = gtk_source_gutter_get_instance_private (self);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gint
Packit a7d494
sort_by_position (Renderer *r1,
Packit a7d494
                  Renderer *r2,
Packit a7d494
                  gpointer  data)
Packit a7d494
{
Packit a7d494
	if (r1->position < r2->position)
Packit a7d494
	{
Packit a7d494
		return -1;
Packit a7d494
	}
Packit a7d494
	else if (r1->position > r2->position)
Packit a7d494
	{
Packit a7d494
		return 1;
Packit a7d494
	}
Packit a7d494
	else
Packit a7d494
	{
Packit a7d494
		return 0;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
append_renderer (GtkSourceGutter *gutter,
Packit a7d494
                 Renderer        *renderer)
Packit a7d494
{
Packit a7d494
	gutter->priv->renderers =
Packit a7d494
		g_list_insert_sorted_with_data (gutter->priv->renderers,
Packit a7d494
		                                renderer,
Packit a7d494
		                                (GCompareDataFunc)sort_by_position,
Packit a7d494
		                                NULL);
Packit a7d494
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
GtkSourceGutter *
Packit a7d494
_gtk_source_gutter_new (GtkSourceView     *view,
Packit a7d494
			GtkTextWindowType  type)
Packit a7d494
{
Packit a7d494
	return g_object_new (GTK_SOURCE_TYPE_GUTTER,
Packit a7d494
	                     "view", view,
Packit a7d494
	                     "window_type", type,
Packit a7d494
	                     NULL);
Packit a7d494
}
Packit a7d494
Packit a7d494
/* Public API */
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_get_view:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 *
Packit a7d494
 * Returns: (transfer none): the associated #GtkSourceView.
Packit a7d494
 * Since: 3.24
Packit a7d494
 */
Packit a7d494
GtkSourceView *
Packit a7d494
gtk_source_gutter_get_view (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), NULL);
Packit a7d494
Packit a7d494
	return gutter->priv->view;
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_get_window_type:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 *
Packit a7d494
 * Returns: the #GtkTextWindowType of @gutter.
Packit a7d494
 * Since: 3.24
Packit a7d494
 */
Packit a7d494
GtkTextWindowType
Packit a7d494
gtk_source_gutter_get_window_type (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), GTK_TEXT_WINDOW_PRIVATE);
Packit a7d494
Packit a7d494
	return gutter->priv->window_type;
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_get_window:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 *
Packit a7d494
 * Get the #GdkWindow of the gutter. The window will only be available when the
Packit a7d494
 * gutter has at least one, non-zero width, cell renderer packed.
Packit a7d494
 *
Packit a7d494
 * Returns: (transfer none): the #GdkWindow of the gutter, or %NULL
Packit a7d494
 * if the gutter has no window.
Packit a7d494
 *
Packit a7d494
 * Since: 2.8
Packit a7d494
 * Deprecated: 3.12: Use gtk_text_view_get_window() instead.
Packit a7d494
 */
Packit a7d494
GdkWindow *
Packit a7d494
gtk_source_gutter_get_window (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), NULL);
Packit a7d494
	g_return_val_if_fail (gutter->priv->view != NULL, NULL);
Packit a7d494
Packit a7d494
	return get_window (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_insert:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 * @renderer: a gutter renderer (must inherit from #GtkSourceGutterRenderer).
Packit a7d494
 * @position: the renderer position.
Packit a7d494
 *
Packit a7d494
 * Insert @renderer into the gutter. If @renderer is yet unowned then gutter
Packit a7d494
 * claims its ownership. Otherwise just increases renderer's reference count.
Packit a7d494
 * @renderer cannot be already inserted to another gutter.
Packit a7d494
 *
Packit a7d494
 * Returns: %TRUE if operation succeeded. Otherwise %FALSE.
Packit a7d494
 *
Packit a7d494
 * Since: 3.0
Packit a7d494
 *
Packit a7d494
 **/
Packit a7d494
gboolean
Packit a7d494
gtk_source_gutter_insert (GtkSourceGutter         *gutter,
Packit a7d494
                          GtkSourceGutterRenderer *renderer,
Packit a7d494
                          gint                     position)
Packit a7d494
{
Packit a7d494
	Renderer* internal_renderer;
Packit a7d494
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), FALSE);
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), FALSE);
Packit a7d494
	g_return_val_if_fail (gtk_source_gutter_renderer_get_view (renderer) == NULL, FALSE);
Packit a7d494
	g_return_val_if_fail (gtk_source_gutter_renderer_get_window_type (renderer) == GTK_TEXT_WINDOW_PRIVATE, FALSE);
Packit a7d494
Packit a7d494
	internal_renderer = renderer_new (gutter, renderer, position);
Packit a7d494
	append_renderer (gutter, internal_renderer);
Packit a7d494
Packit a7d494
	return TRUE;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
renderer_find (GtkSourceGutter          *gutter,
Packit a7d494
               GtkSourceGutterRenderer  *renderer,
Packit a7d494
               Renderer                **ret,
Packit a7d494
               GList                   **retlist)
Packit a7d494
{
Packit a7d494
	GList *list;
Packit a7d494
Packit a7d494
	for (list = gutter->priv->renderers; list; list = g_list_next (list))
Packit a7d494
	{
Packit a7d494
		*ret = list->data;
Packit a7d494
Packit a7d494
		if ((*ret)->renderer == renderer)
Packit a7d494
		{
Packit a7d494
			if (retlist)
Packit a7d494
			{
Packit a7d494
				*retlist = list;
Packit a7d494
			}
Packit a7d494
Packit a7d494
			return TRUE;
Packit a7d494
		}
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return FALSE;
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_reorder:
Packit a7d494
 * @gutter: a #GtkSourceGutterRenderer.
Packit a7d494
 * @renderer: a #GtkCellRenderer.
Packit a7d494
 * @position: the new renderer position.
Packit a7d494
 *
Packit a7d494
 * Reorders @renderer in @gutter to new @position.
Packit a7d494
 *
Packit a7d494
 * Since: 2.8
Packit a7d494
 */
Packit a7d494
void
Packit a7d494
gtk_source_gutter_reorder (GtkSourceGutter         *gutter,
Packit a7d494
                           GtkSourceGutterRenderer *renderer,
Packit a7d494
                           gint                     position)
Packit a7d494
{
Packit a7d494
	Renderer *ret;
Packit a7d494
	GList *retlist;
Packit a7d494
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
Packit a7d494
Packit a7d494
	if (renderer_find (gutter, renderer, &ret, &retlist))
Packit a7d494
	{
Packit a7d494
		gutter->priv->renderers =
Packit a7d494
			g_list_delete_link (gutter->priv->renderers,
Packit a7d494
			                    retlist);
Packit a7d494
Packit a7d494
		ret->position = position;
Packit a7d494
		append_renderer (gutter, ret);
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_remove:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 * @renderer: a #GtkSourceGutterRenderer.
Packit a7d494
 *
Packit a7d494
 * Removes @renderer from @gutter.
Packit a7d494
 *
Packit a7d494
 * Since: 2.8
Packit a7d494
 */
Packit a7d494
void
Packit a7d494
gtk_source_gutter_remove (GtkSourceGutter         *gutter,
Packit a7d494
                          GtkSourceGutterRenderer *renderer)
Packit a7d494
{
Packit a7d494
	Renderer *ret;
Packit a7d494
	GList *retlist;
Packit a7d494
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
Packit a7d494
Packit a7d494
	if (renderer_find (gutter, renderer, &ret, &retlist))
Packit a7d494
	{
Packit a7d494
		gutter->priv->renderers =
Packit a7d494
			g_list_delete_link (gutter->priv->renderers,
Packit a7d494
			                    retlist);
Packit a7d494
Packit a7d494
		update_gutter_size (gutter);
Packit a7d494
		renderer_free (ret);
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_queue_draw:
Packit a7d494
 * @gutter: a #GtkSourceGutter.
Packit a7d494
 *
Packit a7d494
 * Invalidates the drawable area of the gutter. You can use this to force a
Packit a7d494
 * redraw of the gutter if something has changed and needs to be redrawn.
Packit a7d494
 *
Packit a7d494
 * Since: 2.8
Packit a7d494
 */
Packit a7d494
void
Packit a7d494
gtk_source_gutter_queue_draw (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
Packit a7d494
Packit a7d494
	do_redraw (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
typedef struct _LinesInfo LinesInfo;
Packit a7d494
Packit a7d494
struct _LinesInfo
Packit a7d494
{
Packit a7d494
	gint total_height;
Packit a7d494
	gint lines_count;
Packit a7d494
	GArray *buffer_coords;
Packit a7d494
	GArray *line_heights;
Packit a7d494
	GArray *line_numbers;
Packit a7d494
	GtkTextIter start;
Packit a7d494
	GtkTextIter end;
Packit a7d494
};
Packit a7d494
Packit a7d494
static LinesInfo *
Packit a7d494
lines_info_new (void)
Packit a7d494
{
Packit a7d494
	LinesInfo *info;
Packit a7d494
Packit a7d494
	info = g_slice_new0 (LinesInfo);
Packit a7d494
Packit a7d494
	info->buffer_coords = g_array_new (FALSE, FALSE, sizeof (gint));
Packit a7d494
	info->line_heights = g_array_new (FALSE, FALSE, sizeof (gint));
Packit a7d494
	info->line_numbers = g_array_new (FALSE, FALSE, sizeof (gint));
Packit a7d494
Packit a7d494
	return info;
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
lines_info_free (LinesInfo *info)
Packit a7d494
{
Packit a7d494
	if (info != NULL)
Packit a7d494
	{
Packit a7d494
		g_array_free (info->buffer_coords, TRUE);
Packit a7d494
		g_array_free (info->line_heights, TRUE);
Packit a7d494
		g_array_free (info->line_numbers, TRUE);
Packit a7d494
Packit a7d494
		g_slice_free (LinesInfo, info);
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
/* This function is taken and adapted from gtk+/tests/testtext.c */
Packit a7d494
static LinesInfo *
Packit a7d494
get_lines_info (GtkTextView *text_view,
Packit a7d494
		gint         first_y_buffer_coord,
Packit a7d494
		gint         last_y_buffer_coord)
Packit a7d494
{
Packit a7d494
	LinesInfo *info;
Packit a7d494
	GtkTextIter iter;
Packit a7d494
	gint last_line_num = -1;
Packit a7d494
Packit a7d494
	info = lines_info_new ();
Packit a7d494
Packit a7d494
	/* Get iter at first y */
Packit a7d494
	gtk_text_view_get_line_at_y (text_view, &iter, first_y_buffer_coord, NULL);
Packit a7d494
Packit a7d494
	info->start = iter;
Packit a7d494
Packit a7d494
	/* For each iter, get its location and add it to the arrays.
Packit a7d494
	 * Stop when we pass last_y_buffer_coord.
Packit a7d494
	 */
Packit a7d494
	while (!gtk_text_iter_is_end (&iter))
Packit a7d494
	{
Packit a7d494
		gint y;
Packit a7d494
		gint height;
Packit a7d494
		gint line_num;
Packit a7d494
Packit a7d494
		gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
Packit a7d494
Packit a7d494
		g_array_append_val (info->buffer_coords, y);
Packit a7d494
		g_array_append_val (info->line_heights, height);
Packit a7d494
Packit a7d494
		info->total_height += height;
Packit a7d494
Packit a7d494
		line_num = gtk_text_iter_get_line (&iter);
Packit a7d494
		g_array_append_val (info->line_numbers, line_num);
Packit a7d494
Packit a7d494
		last_line_num = line_num;
Packit a7d494
Packit a7d494
		info->lines_count++;
Packit a7d494
Packit a7d494
		if (last_y_buffer_coord <= (y + height))
Packit a7d494
		{
Packit a7d494
			break;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		gtk_text_iter_forward_line (&iter);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (gtk_text_iter_is_end (&iter))
Packit a7d494
	{
Packit a7d494
		gint y;
Packit a7d494
		gint height;
Packit a7d494
		gint line_num;
Packit a7d494
Packit a7d494
		gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
Packit a7d494
Packit a7d494
		line_num = gtk_text_iter_get_line (&iter);
Packit a7d494
Packit a7d494
		if (line_num != last_line_num)
Packit a7d494
		{
Packit a7d494
			g_array_append_val (info->buffer_coords, y);
Packit a7d494
			g_array_append_val (info->line_heights, height);
Packit a7d494
Packit a7d494
			info->total_height += height;
Packit a7d494
Packit a7d494
			g_array_append_val (info->line_numbers, line_num);
Packit a7d494
			info->lines_count++;
Packit a7d494
		}
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (info->lines_count == 0)
Packit a7d494
	{
Packit a7d494
		gint y = 0;
Packit a7d494
		gint n = 0;
Packit a7d494
		gint height;
Packit a7d494
Packit a7d494
		info->lines_count = 1;
Packit a7d494
Packit a7d494
		g_array_append_val (info->buffer_coords, y);
Packit a7d494
		g_array_append_val (info->line_numbers, n);
Packit a7d494
Packit a7d494
		gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
Packit a7d494
		g_array_append_val (info->line_heights, height);
Packit a7d494
Packit a7d494
		info->total_height += height;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	info->end = iter;
Packit a7d494
Packit a7d494
	return info;
Packit a7d494
}
Packit a7d494
Packit a7d494
/* Returns %TRUE if @clip is set. @clip contains the area that should be drawn. */
Packit a7d494
static gboolean
Packit a7d494
get_clip_rectangle (GtkSourceGutter *gutter,
Packit a7d494
		    GtkSourceView   *view,
Packit a7d494
		    cairo_t         *cr,
Packit a7d494
		    GdkRectangle    *clip)
Packit a7d494
{
Packit a7d494
	GdkWindow *window = get_window (gutter);
Packit a7d494
Packit a7d494
	if (window == NULL || !gtk_cairo_should_draw_window (cr, window))
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
Packit a7d494
Packit a7d494
	return gdk_cairo_get_clip_rectangle (cr, clip);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
apply_style (GtkSourceGutter *gutter,
Packit a7d494
	     GtkSourceView   *view,
Packit a7d494
	     GtkStyleContext *style_context,
Packit a7d494
	     cairo_t         *cr)
Packit a7d494
{
Packit a7d494
	const gchar *class;
Packit a7d494
	GdkRGBA fg_color;
Packit a7d494
Packit a7d494
	switch (gutter->priv->window_type)
Packit a7d494
	{
Packit a7d494
		case GTK_TEXT_WINDOW_TOP:
Packit a7d494
			class = GTK_STYLE_CLASS_TOP;
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case GTK_TEXT_WINDOW_RIGHT:
Packit a7d494
			class = GTK_STYLE_CLASS_RIGHT;
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case GTK_TEXT_WINDOW_BOTTOM:
Packit a7d494
			class = GTK_STYLE_CLASS_BOTTOM;
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case GTK_TEXT_WINDOW_LEFT:
Packit a7d494
			class = GTK_STYLE_CLASS_LEFT;
Packit a7d494
			break;
Packit a7d494
Packit a7d494
		case GTK_TEXT_WINDOW_PRIVATE:
Packit a7d494
		case GTK_TEXT_WINDOW_WIDGET:
Packit a7d494
		case GTK_TEXT_WINDOW_TEXT:
Packit a7d494
		default:
Packit a7d494
			g_return_if_reached ();
Packit a7d494
	}
Packit a7d494
Packit a7d494
	/* Apply classes ourselves, since we are in connect_after and so they
Packit a7d494
	 * are not set by gtk.
Packit a7d494
	 */
Packit a7d494
	gtk_style_context_add_class (style_context, class);
Packit a7d494
	gtk_style_context_get_color (style_context,
Packit a7d494
	                             gtk_style_context_get_state (style_context),
Packit a7d494
	                             &fg_color);
Packit a7d494
Packit a7d494
	gdk_cairo_set_source_rgba (cr, &fg_color);
Packit a7d494
}
Packit a7d494
Packit a7d494
/* Call gtk_source_gutter_renderer_begin() on each renderer. */
Packit a7d494
static void
Packit a7d494
begin_draw (GtkSourceGutter *gutter,
Packit a7d494
	    GtkTextView     *view,
Packit a7d494
	    GArray          *renderer_widths,
Packit a7d494
	    LinesInfo       *info,
Packit a7d494
	    cairo_t         *cr)
Packit a7d494
{
Packit a7d494
	GdkRectangle background_area = { 0 };
Packit a7d494
	GdkRectangle cell_area;
Packit a7d494
	GList *l;
Packit a7d494
	gint renderer_num;
Packit a7d494
Packit a7d494
	background_area.x = 0;
Packit a7d494
	background_area.height = info->total_height;
Packit a7d494
Packit a7d494
	gtk_text_view_buffer_to_window_coords (view,
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       0,
Packit a7d494
	                                       g_array_index (info->buffer_coords, gint, 0),
Packit a7d494
	                                       NULL,
Packit a7d494
	                                       &background_area.y);
Packit a7d494
Packit a7d494
	cell_area = background_area;
Packit a7d494
Packit a7d494
	for (l = gutter->priv->renderers, renderer_num = 0;
Packit a7d494
	     l != NULL;
Packit a7d494
	     l = l->next, renderer_num++)
Packit a7d494
	{
Packit a7d494
		Renderer *renderer = l->data;
Packit a7d494
		gint width;
Packit a7d494
		gint xpad;
Packit a7d494
Packit a7d494
		width = g_array_index (renderer_widths, gint, renderer_num);
Packit a7d494
Packit a7d494
		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
		{
Packit a7d494
			g_assert_cmpint (width, ==, 0);
Packit a7d494
			continue;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		gtk_source_gutter_renderer_get_padding (renderer->renderer,
Packit a7d494
							&xpad,
Packit a7d494
							NULL);
Packit a7d494
Packit a7d494
		background_area.width = width;
Packit a7d494
Packit a7d494
		cell_area.width = background_area.width - 2 * xpad;
Packit a7d494
		cell_area.x = background_area.x + xpad;
Packit a7d494
Packit a7d494
		cairo_save (cr);
Packit a7d494
Packit a7d494
		gdk_cairo_rectangle (cr, &background_area);
Packit a7d494
		cairo_clip (cr);
Packit a7d494
Packit a7d494
		gtk_source_gutter_renderer_begin (renderer->renderer,
Packit a7d494
						  cr,
Packit a7d494
						  &background_area,
Packit a7d494
						  &cell_area,
Packit a7d494
						  &info->start,
Packit a7d494
						  &info->end);
Packit a7d494
Packit a7d494
		cairo_restore (cr);
Packit a7d494
Packit a7d494
		background_area.x += background_area.width;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
draw_cells (GtkSourceGutter *gutter,
Packit a7d494
	    GtkTextView     *view,
Packit a7d494
	    GArray          *renderer_widths,
Packit a7d494
	    LinesInfo       *info,
Packit a7d494
	    cairo_t         *cr)
Packit a7d494
{
Packit a7d494
	GtkTextBuffer *buffer;
Packit a7d494
	GtkTextIter insert_iter;
Packit a7d494
	gint cur_line;
Packit a7d494
	GtkTextIter selection_start;
Packit a7d494
	GtkTextIter selection_end;
Packit a7d494
	gint selection_start_line = 0;
Packit a7d494
	gint selection_end_line = 0;
Packit a7d494
	gboolean has_selection;
Packit a7d494
	GtkTextIter start;
Packit a7d494
	gint i;
Packit a7d494
Packit a7d494
	buffer = gtk_text_view_get_buffer (view);
Packit a7d494
Packit a7d494
	gtk_text_buffer_get_iter_at_mark (buffer,
Packit a7d494
	                                  &insert_iter,
Packit a7d494
	                                  gtk_text_buffer_get_insert (buffer));
Packit a7d494
Packit a7d494
	cur_line = gtk_text_iter_get_line (&insert_iter);
Packit a7d494
Packit a7d494
	has_selection = gtk_text_buffer_get_selection_bounds (buffer,
Packit a7d494
	                                                      &selection_start,
Packit a7d494
	                                                      &selection_end);
Packit a7d494
Packit a7d494
	if (has_selection)
Packit a7d494
	{
Packit a7d494
		selection_start_line = gtk_text_iter_get_line (&selection_start);
Packit a7d494
		selection_end_line = gtk_text_iter_get_line (&selection_end);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	start = info->start;
Packit a7d494
	i = 0;
Packit a7d494
Packit a7d494
	while (i < info->lines_count)
Packit a7d494
	{
Packit a7d494
		GtkTextIter end;
Packit a7d494
		GdkRectangle background_area;
Packit a7d494
		GtkSourceGutterRendererState state;
Packit a7d494
		gint pos;
Packit a7d494
		gint line_to_paint;
Packit a7d494
		gint renderer_num;
Packit a7d494
		GList *l;
Packit a7d494
Packit a7d494
		end = start;
Packit a7d494
Packit a7d494
		if (!gtk_text_iter_ends_line (&end))
Packit a7d494
		{
Packit a7d494
			/*
Packit a7d494
			 * It turns out that gtk_text_iter_forward_to_line_end
Packit a7d494
			 * is slower than jumping to the next line in the
Packit a7d494
			 * btree index and then moving backwards a character.
Packit a7d494
			 * We don't really care that we might be after the
Packit a7d494
			 * newline breaking characters, since those are part
Packit a7d494
			 * of the same line (rather than the next line).
Packit a7d494
			 */
Packit a7d494
			if (gtk_text_iter_forward_line (&end))
Packit a7d494
			{
Packit a7d494
				gtk_text_iter_backward_char (&end;;
Packit a7d494
			}
Packit a7d494
		}
Packit a7d494
Packit a7d494
		/* Possible improvement: if buffer and window coords have the
Packit a7d494
		 * same unit, there are probably some possible performance
Packit a7d494
		 * improvements by avoiding some buffer <-> window coords
Packit a7d494
		 * conversions.
Packit a7d494
		 */
Packit a7d494
		gtk_text_view_buffer_to_window_coords (view,
Packit a7d494
		                                       gutter->priv->window_type,
Packit a7d494
		                                       0,
Packit a7d494
		                                       g_array_index (info->buffer_coords, gint, i),
Packit a7d494
		                                       NULL,
Packit a7d494
		                                       &pos;;
Packit a7d494
Packit a7d494
		line_to_paint = g_array_index (info->line_numbers, gint, i);
Packit a7d494
Packit a7d494
		background_area.y = pos;
Packit a7d494
		background_area.height = g_array_index (info->line_heights, gint, i);
Packit a7d494
		background_area.x = 0;
Packit a7d494
Packit a7d494
		state = GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL;
Packit a7d494
Packit a7d494
		if (line_to_paint == cur_line)
Packit a7d494
		{
Packit a7d494
			state |= GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		if (has_selection &&
Packit a7d494
		    selection_start_line <= line_to_paint && line_to_paint <= selection_end_line)
Packit a7d494
		{
Packit a7d494
			state |= GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		for (l = gutter->priv->renderers, renderer_num = 0;
Packit a7d494
		     l != NULL;
Packit a7d494
		     l = l->next, renderer_num++)
Packit a7d494
		{
Packit a7d494
			Renderer *renderer;
Packit a7d494
			GdkRectangle cell_area;
Packit a7d494
			gint width;
Packit a7d494
			gint xpad;
Packit a7d494
			gint ypad;
Packit a7d494
Packit a7d494
			renderer = l->data;
Packit a7d494
			width = g_array_index (renderer_widths, gint, renderer_num);
Packit a7d494
Packit a7d494
			if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
			{
Packit a7d494
				g_assert_cmpint (width, ==, 0);
Packit a7d494
				continue;
Packit a7d494
			}
Packit a7d494
Packit a7d494
			gtk_source_gutter_renderer_get_padding (renderer->renderer,
Packit a7d494
			                                        &xpad,
Packit a7d494
			                                        &ypad);
Packit a7d494
Packit a7d494
			background_area.width = width;
Packit a7d494
Packit a7d494
			cell_area.y = background_area.y + ypad;
Packit a7d494
			cell_area.height = background_area.height - 2 * ypad;
Packit a7d494
Packit a7d494
			cell_area.x = background_area.x + xpad;
Packit a7d494
			cell_area.width = background_area.width - 2 * xpad;
Packit a7d494
Packit a7d494
			if (renderer->prelit >= 0 &&
Packit a7d494
			    cell_area.y <= renderer->prelit && renderer->prelit <= cell_area.y + cell_area.height)
Packit a7d494
			{
Packit a7d494
				state |= GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
Packit a7d494
			}
Packit a7d494
Packit a7d494
			gtk_source_gutter_renderer_query_data (renderer->renderer,
Packit a7d494
			                                       &start,
Packit a7d494
			                                       &end,
Packit a7d494
			                                       state);
Packit a7d494
Packit a7d494
			cairo_save (cr);
Packit a7d494
Packit a7d494
			gdk_cairo_rectangle (cr, &background_area);
Packit a7d494
Packit a7d494
			cairo_clip (cr);
Packit a7d494
Packit a7d494
			/* Call render with correct area */
Packit a7d494
			gtk_source_gutter_renderer_draw (renderer->renderer,
Packit a7d494
			                                 cr,
Packit a7d494
			                                 &background_area,
Packit a7d494
			                                 &cell_area,
Packit a7d494
			                                 &start,
Packit a7d494
			                                 &end,
Packit a7d494
			                                 state);
Packit a7d494
Packit a7d494
			cairo_restore (cr);
Packit a7d494
Packit a7d494
			background_area.x += background_area.width;
Packit a7d494
			state &= ~GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		i++;
Packit a7d494
		gtk_text_iter_forward_line (&start;;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
end_draw (GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	GList *l;
Packit a7d494
Packit a7d494
	for (l = gutter->priv->renderers; l != NULL; l = l->next)
Packit a7d494
	{
Packit a7d494
		Renderer *renderer = l->data;
Packit a7d494
Packit a7d494
		if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
		{
Packit a7d494
			gtk_source_gutter_renderer_end (renderer->renderer);
Packit a7d494
		}
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
void
Packit a7d494
_gtk_source_gutter_draw (GtkSourceGutter *gutter,
Packit a7d494
			 GtkSourceView   *view,
Packit a7d494
			 cairo_t         *cr)
Packit a7d494
{
Packit a7d494
	GdkRectangle clip;
Packit a7d494
	GtkTextView *text_view;
Packit a7d494
	gint first_y_window_coord;
Packit a7d494
	gint last_y_window_coord;
Packit a7d494
	gint first_y_buffer_coord;
Packit a7d494
	gint last_y_buffer_coord;
Packit a7d494
	GArray *renderer_widths;
Packit a7d494
	LinesInfo *info;
Packit a7d494
	GtkStyleContext *style_context;
Packit a7d494
Packit a7d494
	if (!get_clip_rectangle (gutter, view, cr, &clip))
Packit a7d494
	{
Packit a7d494
		return;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gutter->priv->is_drawing = TRUE;
Packit a7d494
Packit a7d494
	renderer_widths = g_array_new (FALSE, FALSE, sizeof (gint));
Packit a7d494
	calculate_gutter_size (gutter, renderer_widths);
Packit a7d494
Packit a7d494
	text_view = GTK_TEXT_VIEW (view);
Packit a7d494
Packit a7d494
	first_y_window_coord = clip.y;
Packit a7d494
	last_y_window_coord = first_y_window_coord + clip.height;
Packit a7d494
Packit a7d494
	/* get the extents of the line printing */
Packit a7d494
	gtk_text_view_window_to_buffer_coords (text_view,
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       0,
Packit a7d494
	                                       first_y_window_coord,
Packit a7d494
	                                       NULL,
Packit a7d494
	                                       &first_y_buffer_coord);
Packit a7d494
Packit a7d494
	gtk_text_view_window_to_buffer_coords (text_view,
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       0,
Packit a7d494
	                                       last_y_window_coord,
Packit a7d494
	                                       NULL,
Packit a7d494
	                                       &last_y_buffer_coord);
Packit a7d494
Packit a7d494
	info = get_lines_info (text_view,
Packit a7d494
			       first_y_buffer_coord,
Packit a7d494
			       last_y_buffer_coord);
Packit a7d494
Packit a7d494
	style_context = gtk_widget_get_style_context (GTK_WIDGET (view));
Packit a7d494
	gtk_style_context_save (style_context);
Packit a7d494
	apply_style (gutter, view, style_context, cr);
Packit a7d494
Packit a7d494
	begin_draw (gutter,
Packit a7d494
		    text_view,
Packit a7d494
		    renderer_widths,
Packit a7d494
		    info,
Packit a7d494
		    cr);
Packit a7d494
Packit a7d494
	draw_cells (gutter,
Packit a7d494
		    text_view,
Packit a7d494
		    renderer_widths,
Packit a7d494
		    info,
Packit a7d494
		    cr);
Packit a7d494
Packit a7d494
	/* Allow to call queue_redraw() in ::end. */
Packit a7d494
	gutter->priv->is_drawing = FALSE;
Packit a7d494
Packit a7d494
	end_draw (gutter);
Packit a7d494
Packit a7d494
	gtk_style_context_restore (style_context);
Packit a7d494
Packit a7d494
	g_array_free (renderer_widths, TRUE);
Packit a7d494
	lines_info_free (info);
Packit a7d494
}
Packit a7d494
Packit a7d494
static Renderer *
Packit a7d494
renderer_at_x (GtkSourceGutter *gutter,
Packit a7d494
               gint             x,
Packit a7d494
               gint            *start,
Packit a7d494
               gint            *width)
Packit a7d494
{
Packit a7d494
	GList *item;
Packit a7d494
	gint s;
Packit a7d494
	gint w;
Packit a7d494
Packit a7d494
	update_gutter_size (gutter);
Packit a7d494
Packit a7d494
	s = 0;
Packit a7d494
Packit a7d494
	for (item = gutter->priv->renderers; item; item = g_list_next (item))
Packit a7d494
	{
Packit a7d494
		Renderer *renderer = item->data;
Packit a7d494
		gint xpad;
Packit a7d494
Packit a7d494
		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
		{
Packit a7d494
			continue;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		w = gtk_source_gutter_renderer_get_size (renderer->renderer);
Packit a7d494
Packit a7d494
		gtk_source_gutter_renderer_get_padding (renderer->renderer,
Packit a7d494
		                                        &xpad,
Packit a7d494
		                                        NULL);
Packit a7d494
Packit a7d494
		s += xpad;
Packit a7d494
Packit a7d494
		if (w > 0 && x >= s && x < s + w)
Packit a7d494
		{
Packit a7d494
			if (width)
Packit a7d494
			{
Packit a7d494
				*width = w;
Packit a7d494
			}
Packit a7d494
Packit a7d494
			if (start)
Packit a7d494
			{
Packit a7d494
				*start = s;
Packit a7d494
			}
Packit a7d494
Packit a7d494
			return renderer;
Packit a7d494
		}
Packit a7d494
Packit a7d494
		s += w + xpad;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return NULL;
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
get_renderer_rect (GtkSourceGutter *gutter,
Packit a7d494
                   Renderer        *renderer,
Packit a7d494
                   GtkTextIter     *iter,
Packit a7d494
                   gint             line,
Packit a7d494
                   GdkRectangle    *rectangle,
Packit a7d494
                   gint             start)
Packit a7d494
{
Packit a7d494
	gint y;
Packit a7d494
	gint ypad;
Packit a7d494
Packit a7d494
	rectangle->x = start;
Packit a7d494
Packit a7d494
	gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                               iter,
Packit a7d494
	                               &y,
Packit a7d494
	                               &rectangle->height);
Packit a7d494
Packit a7d494
	rectangle->width = gtk_source_gutter_renderer_get_size (renderer->renderer);
Packit a7d494
Packit a7d494
	gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       0,
Packit a7d494
	                                       y,
Packit a7d494
	                                       NULL,
Packit a7d494
	                                       &rectangle->y);
Packit a7d494
Packit a7d494
	gtk_source_gutter_renderer_get_padding (renderer->renderer,
Packit a7d494
	                                        NULL,
Packit a7d494
	                                        &ypad);
Packit a7d494
Packit a7d494
	rectangle->y += ypad;
Packit a7d494
	rectangle->height -= 2 * ypad;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
renderer_query_activatable (GtkSourceGutter *gutter,
Packit a7d494
                            Renderer        *renderer,
Packit a7d494
                            GdkEvent        *event,
Packit a7d494
                            gint             x,
Packit a7d494
                            gint             y,
Packit a7d494
                            GtkTextIter     *line_iter,
Packit a7d494
                            GdkRectangle    *rect,
Packit a7d494
                            gint             start)
Packit a7d494
{
Packit a7d494
	gint y_buf;
Packit a7d494
	gint yline;
Packit a7d494
	GtkTextIter iter;
Packit a7d494
	GdkRectangle r;
Packit a7d494
Packit a7d494
	if (!renderer)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       x,
Packit a7d494
	                                       y,
Packit a7d494
	                                       NULL,
Packit a7d494
	                                       &y_buf);
Packit a7d494
Packit a7d494
	gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (gutter->priv->view),
Packit a7d494
	                             &iter,
Packit a7d494
	                             y_buf,
Packit a7d494
	                             &yline);
Packit a7d494
Packit a7d494
	if (yline > y_buf)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	get_renderer_rect (gutter, renderer, &iter, yline, &r, start);
Packit a7d494
Packit a7d494
	if (line_iter)
Packit a7d494
	{
Packit a7d494
		*line_iter = iter;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (rect)
Packit a7d494
	{
Packit a7d494
		*rect = r;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (y < r.y || y > r.y + r.height)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return gtk_source_gutter_renderer_query_activatable (renderer->renderer,
Packit a7d494
	                                                     &iter,
Packit a7d494
	                                                     &r,
Packit a7d494
	                                                     event);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
redraw_for_window (GtkSourceGutter *gutter,
Packit a7d494
		   GdkEvent        *event,
Packit a7d494
		   gboolean         act_on_window,
Packit a7d494
		   gint             x,
Packit a7d494
		   gint             y)
Packit a7d494
{
Packit a7d494
	Renderer *at_x = NULL;
Packit a7d494
	gint start = 0;
Packit a7d494
	GList *item;
Packit a7d494
	gboolean redraw;
Packit a7d494
Packit a7d494
	if (event->any.window != get_window (gutter) && act_on_window)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (act_on_window)
Packit a7d494
	{
Packit a7d494
		at_x = renderer_at_x (gutter, x, &start, NULL);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	redraw = FALSE;
Packit a7d494
Packit a7d494
	for (item = gutter->priv->renderers; item; item = g_list_next (item))
Packit a7d494
	{
Packit a7d494
		Renderer *renderer = item->data;
Packit a7d494
		gint prelit = renderer->prelit;
Packit a7d494
Packit a7d494
		if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
Packit a7d494
		{
Packit a7d494
			renderer->prelit = -1;
Packit a7d494
		}
Packit a7d494
		else
Packit a7d494
		{
Packit a7d494
			if (renderer != at_x || !act_on_window)
Packit a7d494
			{
Packit a7d494
				renderer->prelit = -1;
Packit a7d494
			}
Packit a7d494
			else if (renderer_query_activatable (gutter,
Packit a7d494
			                                     renderer,
Packit a7d494
			                                     event,
Packit a7d494
			                                     x,
Packit a7d494
			                                     y,
Packit a7d494
			                                     NULL,
Packit a7d494
			                                     NULL,
Packit a7d494
			                                     start))
Packit a7d494
			{
Packit a7d494
				renderer->prelit = y;
Packit a7d494
			}
Packit a7d494
			else
Packit a7d494
			{
Packit a7d494
				renderer->prelit = -1;
Packit a7d494
			}
Packit a7d494
		}
Packit a7d494
Packit a7d494
		redraw |= (renderer->prelit != prelit);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (redraw)
Packit a7d494
	{
Packit a7d494
		do_redraw (gutter);
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return FALSE;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
on_view_motion_notify_event (GtkSourceView    *view,
Packit a7d494
                             GdkEventMotion   *event,
Packit a7d494
                             GtkSourceGutter  *gutter)
Packit a7d494
{
Packit a7d494
	return redraw_for_window (gutter,
Packit a7d494
	                          (GdkEvent *)event,
Packit a7d494
	                          TRUE,
Packit a7d494
	                          (gint)event->x,
Packit a7d494
	                          (gint)event->y);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
on_view_enter_notify_event (GtkSourceView     *view,
Packit a7d494
                            GdkEventCrossing  *event,
Packit a7d494
                            GtkSourceGutter   *gutter)
Packit a7d494
{
Packit a7d494
	return redraw_for_window (gutter,
Packit a7d494
	                          (GdkEvent *)event,
Packit a7d494
	                          TRUE,
Packit a7d494
	                          (gint)event->x,
Packit a7d494
	                          (gint)event->y);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
on_view_leave_notify_event (GtkSourceView     *view,
Packit a7d494
                            GdkEventCrossing  *event,
Packit a7d494
                            GtkSourceGutter   *gutter)
Packit a7d494
{
Packit a7d494
	return redraw_for_window (gutter,
Packit a7d494
	                          (GdkEvent *)event,
Packit a7d494
	                          FALSE,
Packit a7d494
	                          (gint)event->x,
Packit a7d494
	                          (gint)event->y);
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
on_view_button_press_event (GtkSourceView    *view,
Packit a7d494
                            GdkEventButton   *event,
Packit a7d494
                            GtkSourceGutter  *gutter)
Packit a7d494
{
Packit a7d494
	Renderer *renderer;
Packit a7d494
	GtkTextIter line_iter;
Packit a7d494
	gint start = -1;
Packit a7d494
	GdkRectangle rect;
Packit a7d494
Packit a7d494
	if (event->window != get_window (gutter))
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (event->type != GDK_BUTTON_PRESS)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	/* Check cell renderer */
Packit a7d494
	renderer = renderer_at_x (gutter, event->x, &start, NULL);
Packit a7d494
Packit a7d494
	if (renderer_query_activatable (gutter,
Packit a7d494
	                                renderer,
Packit a7d494
	                                (GdkEvent *)event,
Packit a7d494
	                                (gint)event->x,
Packit a7d494
	                                (gint)event->y,
Packit a7d494
	                                &line_iter,
Packit a7d494
	                                &rect,
Packit a7d494
	                                start))
Packit a7d494
	{
Packit a7d494
		gtk_source_gutter_renderer_activate (renderer->renderer,
Packit a7d494
		                                     &line_iter,
Packit a7d494
		                                     &rect,
Packit a7d494
		                                     (GdkEvent *)event);
Packit a7d494
Packit a7d494
		do_redraw (gutter);
Packit a7d494
Packit a7d494
		return TRUE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return FALSE;
Packit a7d494
}
Packit a7d494
Packit a7d494
static gboolean
Packit a7d494
on_view_query_tooltip (GtkSourceView   *view,
Packit a7d494
                       gint             x,
Packit a7d494
                       gint             y,
Packit a7d494
                       gboolean         keyboard_mode,
Packit a7d494
                       GtkTooltip      *tooltip,
Packit a7d494
                       GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	GtkTextView *text_view = GTK_TEXT_VIEW (view);
Packit a7d494
	Renderer *renderer;
Packit a7d494
	gint start = 0;
Packit a7d494
	gint width = 0;
Packit a7d494
	gint y_buf;
Packit a7d494
	gint yline;
Packit a7d494
	GtkTextIter line_iter;
Packit a7d494
	GdkRectangle rect;
Packit a7d494
Packit a7d494
	if (keyboard_mode)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	/* Check cell renderer */
Packit a7d494
	renderer = renderer_at_x (gutter, x, &start, &width);
Packit a7d494
Packit a7d494
	if (!renderer)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	gtk_text_view_window_to_buffer_coords (text_view,
Packit a7d494
	                                       gutter->priv->window_type,
Packit a7d494
	                                       x, y,
Packit a7d494
	                                       NULL, &y_buf);
Packit a7d494
Packit a7d494
	gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (view),
Packit a7d494
	                             &line_iter,
Packit a7d494
	                             y_buf,
Packit a7d494
	                             &yline);
Packit a7d494
Packit a7d494
	if (yline > y_buf)
Packit a7d494
	{
Packit a7d494
		return FALSE;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	get_renderer_rect (gutter,
Packit a7d494
	                   renderer,
Packit a7d494
	                   &line_iter,
Packit a7d494
	                   yline,
Packit a7d494
	                   &rect,
Packit a7d494
	                   start);
Packit a7d494
Packit a7d494
	return gtk_source_gutter_renderer_query_tooltip (renderer->renderer,
Packit a7d494
	                                                 &line_iter,
Packit a7d494
	                                                 &rect,
Packit a7d494
	                                                 x,
Packit a7d494
	                                                 y,
Packit a7d494
	                                                 tooltip);
Packit a7d494
}
Packit a7d494
Packit a7d494
static void
Packit a7d494
on_view_style_updated (GtkSourceView   *view,
Packit a7d494
                       GtkSourceGutter *gutter)
Packit a7d494
{
Packit a7d494
	gtk_source_gutter_queue_draw (gutter);
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_set_padding:
Packit a7d494
 * @gutter:
Packit a7d494
 * @xpad:
Packit a7d494
 * @ypad:
Packit a7d494
 *
Packit a7d494
 * Deprecated: 3.12: Use gtk_source_gutter_renderer_set_padding() instead.
Packit a7d494
 */
Packit a7d494
void
Packit a7d494
gtk_source_gutter_set_padding (GtkSourceGutter *gutter,
Packit a7d494
                               gint             xpad,
Packit a7d494
                               gint             ypad)
Packit a7d494
{
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
Packit a7d494
Packit a7d494
	if (set_xpad (gutter, xpad, FALSE) || set_ypad (gutter, ypad, FALSE))
Packit a7d494
	{
Packit a7d494
		update_gutter_size (gutter);
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_get_padding:
Packit a7d494
 * @gutter:
Packit a7d494
 * @xpad:
Packit a7d494
 * @ypad:
Packit a7d494
 *
Packit a7d494
 * Deprecated: 3.12: Use gtk_source_gutter_renderer_get_padding() instead.
Packit a7d494
 */
Packit a7d494
void
Packit a7d494
gtk_source_gutter_get_padding (GtkSourceGutter *gutter,
Packit a7d494
                               gint            *xpad,
Packit a7d494
                               gint            *ypad)
Packit a7d494
{
Packit a7d494
	g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
Packit a7d494
Packit a7d494
	if (xpad)
Packit a7d494
	{
Packit a7d494
		*xpad = gutter->priv->xpad;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	if (ypad)
Packit a7d494
	{
Packit a7d494
		*ypad = gutter->priv->ypad;
Packit a7d494
	}
Packit a7d494
}
Packit a7d494
Packit a7d494
/**
Packit a7d494
 * gtk_source_gutter_get_renderer_at_pos:
Packit a7d494
 * @gutter: A #GtkSourceGutter.
Packit a7d494
 * @x: The x position to get identified.
Packit a7d494
 * @y: The y position to get identified.
Packit a7d494
 *
Packit a7d494
 * Finds the #GtkSourceGutterRenderer at (x, y).
Packit a7d494
 *
Packit a7d494
 * Returns: (nullable) (transfer none): the renderer at (x, y) or %NULL.
Packit a7d494
 */
Packit a7d494
/* TODO: better document this function. The (x,y) position is different from
Packit a7d494
 * the position passed to gtk_source_gutter_insert() and
Packit a7d494
 * gtk_source_gutter_reorder(). The (x,y) coordinate can come from a click
Packit a7d494
 * event, for example? Is the (x,y) a coordinate of the Gutter's GdkWindow?
Packit a7d494
 * Where is the (0,0)? And so on.
Packit a7d494
 * Also, this function doesn't seem to be used.
Packit a7d494
 */
Packit a7d494
GtkSourceGutterRenderer *
Packit a7d494
gtk_source_gutter_get_renderer_at_pos (GtkSourceGutter *gutter,
Packit a7d494
                                       gint             x,
Packit a7d494
                                       gint             y)
Packit a7d494
{
Packit a7d494
	Renderer *renderer;
Packit a7d494
Packit a7d494
	g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), NULL);
Packit a7d494
Packit a7d494
	renderer = renderer_at_x (gutter, x, NULL, NULL);
Packit a7d494
Packit a7d494
	if (renderer == NULL)
Packit a7d494
	{
Packit a7d494
		return NULL;
Packit a7d494
	}
Packit a7d494
Packit a7d494
	return renderer->renderer;
Packit a7d494
}