[gtksourceview/wip/chergert/gsv-gtk4: 106/131] gutter: port to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/gsv-gtk4: 106/131] gutter: port to GTK 4
- Date: Wed, 29 Jan 2020 17:26:25 +0000 (UTC)
commit 97829416be3fcc6df566a32c5f03f97a6a907623
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 15 14:53:52 2020 -0800
gutter: port to GTK 4
- Use widgets instead of GInitiallyUnowned. This allows for much more
advanced usage of event controllers, snapshoting, and potentially
caching of render nodes.
- GtkSourceGutter is now a container of GtkSourceGutterRenderer
- Remove use of GdkEvent as much as possible and instead follow patterns
for events more closely to upstream GTK 4. In particular the query
and activate signals provide button/state/n_presses which are typically
what would be needed by renderers anyway.
- Tooltips can now be handled by renderers directly using the GtkWidget
infrastructure for that.
- Use GtkSourceGutterLines to reduce the number of passes we do through
the textbuffer btree. This helps achieve a few more frames per second
in the rendering pipeline during heavy kinetic scrolling. Especially
on HiDPI systems.
- Use GdkPaintable instead of GdkPixbuf for rendering pixbufs.
- Add alignment helper for renderers to center on a particular position.
This caches the positioning so that it can be reused by additional
cell renderers without the extra floating point math or view area
location.
- Renderer state is no longer necessary as that information can be
retrieved from the GtkSourceGutterLines using the helper functions.
State is simply a quark in the quarkset like any other status.
gtksourceview/gtksourcegutter-private.h | 10 +-
gtksourceview/gtksourcegutter.c | 1630 ++++++++---------------
gtksourceview/gtksourcegutter.h | 27 +-
gtksourceview/gtksourcegutterrenderer-private.h | 15 +-
gtksourceview/gtksourcegutterrenderer.c | 1445 +++++++-------------
gtksourceview/gtksourcegutterrenderer.h | 187 +--
gtksourceview/gtksourcegutterrendererlines.c | 304 ++---
gtksourceview/gtksourcegutterrenderermarks.c | 155 +--
gtksourceview/gtksourcegutterrendererpixbuf.c | 278 ++--
gtksourceview/gtksourcegutterrendererpixbuf.h | 28 +-
gtksourceview/gtksourcegutterrenderertext.c | 242 ++--
11 files changed, 1600 insertions(+), 2721 deletions(-)
---
diff --git a/gtksourceview/gtksourcegutter-private.h b/gtksourceview/gtksourcegutter-private.h
index e1ebeb8a..a976b541 100644
--- a/gtksourceview/gtksourcegutter-private.h
+++ b/gtksourceview/gtksourcegutter-private.h
@@ -21,16 +21,16 @@
#pragma once
#include <gtk/gtk.h>
+
#include "gtksourcetypes.h"
G_BEGIN_DECLS
G_GNUC_INTERNAL
-GtkSourceGutter *_gtk_source_gutter_new (GtkSourceView *view,
- GtkTextWindowType type);
+GtkSourceGutter *_gtk_source_gutter_new (GtkTextWindowType type);
+G_GNUC_INTERNAL
+GtkSourceGutterLines *_gtk_source_gutter_get_lines (GtkSourceGutter *gutter);
G_GNUC_INTERNAL
-void _gtk_source_gutter_draw (GtkSourceGutter *gutter,
- GtkSourceView *view,
- cairo_t *cr);
+void _gtk_source_gutter_queue_draw (GtkSourceGutter *gutter);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutter.c b/gtksourceview/gtksourcegutter.c
index 9a988e53..53f48af6 100644
--- a/gtksourceview/gtksourcegutter.c
+++ b/gtksourceview/gtksourcegutter.c
@@ -22,6 +22,8 @@
#include "gtksourcegutter.h"
#include "gtksourcegutter-private.h"
+#include "gtksourcegutterlines.h"
+#include "gtksourcegutterlines-private.h"
#include "gtksourceview.h"
#include "gtksourcegutterrenderer.h"
#include "gtksourcegutterrenderer-private.h"
@@ -62,134 +64,60 @@ typedef struct
gint prelit;
gint position;
-
- gulong queue_draw_handler;
- gulong size_changed_handler;
- gulong notify_xpad_handler;
- gulong notify_ypad_handler;
- gulong notify_visible_handler;
} Renderer;
struct _GtkSourceGutter
{
- GObject parent_instance;
-
- GtkSourceView *view;
- GtkTextWindowType window_type;
- GtkOrientation orientation;
-
- GList *renderers;
-
- guint is_drawing : 1;
-};
+ GtkContainer parent_instance;
-G_DEFINE_TYPE (GtkSourceGutter, gtk_source_gutter, G_TYPE_OBJECT)
-
-static gboolean on_view_motion_notify_event (GtkSourceView *view,
- GdkEventMotion *event,
- GtkSourceGutter *gutter);
-static gboolean on_view_enter_notify_event (GtkSourceView *view,
- GdkEventCrossing *event,
- GtkSourceGutter *gutter);
-static gboolean on_view_leave_notify_event (GtkSourceView *view,
- GdkEventCrossing *event,
- GtkSourceGutter *gutter);
-static gboolean on_view_button_press_event (GtkSourceView *view,
- GdkEventButton *event,
- GtkSourceGutter *gutter);
-static gboolean on_view_query_tooltip (GtkSourceView *view,
- gint x,
- gint y,
- gboolean keyboard_mode,
- GtkTooltip *tooltip,
- GtkSourceGutter *gutter);
-static void on_view_style_updated (GtkSourceView *view,
- GtkSourceGutter *gutter);
-static void do_redraw (GtkSourceGutter *gutter);
-static void update_gutter_size (GtkSourceGutter *gutter);
-
-static GdkWindow *
-get_window (GtkSourceGutter *gutter)
-{
- return gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->view),
- gutter->window_type);
-}
+ GtkSourceView *view;
+ GList *renderers;
+ GtkSourceGutterLines *lines;
-static void
-on_renderer_size_changed (GtkSourceGutterRenderer *renderer,
- GParamSpec *spec,
- GtkSourceGutter *gutter)
-{
- update_gutter_size (gutter);
-}
+ GtkTextWindowType window_type;
+ GtkOrientation orientation;
-static void
-on_renderer_queue_draw (GtkSourceGutterRenderer *renderer,
- GtkSourceGutter *gutter)
-{
- do_redraw (gutter);
-}
+ gulong adj_changed_handler;
+ gulong realize_handler;
+ gulong style_updated_handler;
-static void
-on_renderer_notify_padding (GtkSourceGutterRenderer *renderer,
- GParamSpec *spec,
- GtkSourceGutter *gutter)
-{
- update_gutter_size (gutter);
-}
+ guint is_drawing : 1;
+};
-static void
-on_renderer_notify_visible (GtkSourceGutterRenderer *renderer,
- GParamSpec *spec,
- GtkSourceGutter *gutter)
-{
- update_gutter_size (gutter);
-}
+G_DEFINE_TYPE (GtkSourceGutter, gtk_source_gutter, GTK_TYPE_CONTAINER)
+
+static void gtk_source_gutter_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_source_gutter_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void on_view_style_updated (GtkSourceView *view,
+ GtkSourceGutter *gutter);
+static void on_gutter_pressed_cb (GtkSourceGutter *gutter,
+ gint n_presses,
+ gdouble x,
+ gdouble y,
+ GtkGestureClick *click);
+static void do_redraw (GtkSourceGutter *gutter);
+static void gtk_source_gutter_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot);
+static void gtk_source_gutter_size_allocate (GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline);
static Renderer *
renderer_new (GtkSourceGutter *gutter,
GtkSourceGutterRenderer *renderer,
gint position)
{
- Renderer *ret = g_slice_new0 (Renderer);
+ Renderer *ret;
+ ret = g_slice_new0 (Renderer);
ret->renderer = g_object_ref_sink (renderer);
ret->position = position;
ret->prelit = -1;
- _gtk_source_gutter_renderer_set_view (renderer,
- GTK_TEXT_VIEW (gutter->view),
- gutter->window_type);
-
- 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);
-
- ret->notify_visible_handler =
- g_signal_connect (ret->renderer,
- "notify::visible",
- G_CALLBACK (on_renderer_notify_visible),
- gutter);
+ _gtk_source_gutter_renderer_set_view (renderer, gutter->view);
return ret;
}
@@ -197,40 +125,48 @@ renderer_new (GtkSourceGutter *gutter,
static void
renderer_free (Renderer *renderer)
{
- g_signal_handler_disconnect (renderer->renderer,
- renderer->queue_draw_handler);
-
- 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_signal_handler_disconnect (renderer->renderer,
- renderer->notify_visible_handler);
-
- _gtk_source_gutter_renderer_set_view (renderer->renderer,
- NULL,
- GTK_TEXT_WINDOW_PRIVATE);
+ _gtk_source_gutter_renderer_set_view (renderer->renderer, NULL);
g_object_unref (renderer->renderer);
g_slice_free (Renderer, renderer);
}
static void
-gtk_source_gutter_dispose (GObject *object)
+get_alignment_modes (GtkSourceGutter *gutter,
+ gboolean *needs_wrap_first,
+ gboolean *needs_wrap_last)
{
- GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (object);
+ const GList *list;
+
+ g_assert (GTK_SOURCE_GUTTER (gutter));
+ g_assert (needs_wrap_first != NULL);
+ g_assert (needs_wrap_last != NULL);
+
+ *needs_wrap_first = FALSE;
+ *needs_wrap_last = FALSE;
- g_list_free_full (gutter->renderers, (GDestroyNotify)renderer_free);
- gutter->renderers = NULL;
+ for (list = gutter->renderers; list; list = list->next)
+ {
+ Renderer *renderer = list->data;
+ GtkSourceGutterRendererAlignmentMode mode;
+
+ mode = gtk_source_gutter_renderer_get_alignment_mode (renderer->renderer);
+
+ switch (mode)
+ {
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST:
+ *needs_wrap_first = TRUE;
+ break;
- gutter->view = NULL;
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
+ *needs_wrap_last = TRUE;
+ break;
- G_OBJECT_CLASS (gtk_source_gutter_parent_class)->dispose (object);
+ case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL:
+ default:
+ break;
+ }
+ }
}
static void
@@ -239,16 +175,18 @@ gtk_source_gutter_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- GtkSourceGutter *self = GTK_SOURCE_GUTTER (object);
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (object);
switch (prop_id)
{
case PROP_VIEW:
- g_value_set_object (value, self->view);
+ g_value_set_object (value, gutter->view);
break;
+
case PROP_WINDOW_TYPE:
- g_value_set_enum (value, self->window_type);
+ g_value_set_enum (value, gutter->window_type);
break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -256,143 +194,233 @@ gtk_source_gutter_get_property (GObject *object,
}
static void
-on_view_realize (GtkSourceView *view,
- GtkSourceGutter *gutter)
+on_adjustment_value_changed (GtkAdjustment *adj,
+ GtkSourceGutter *gutter)
+{
+ const GList *list;
+
+ for (list = gutter->renderers; list; list = list->next)
+ {
+ Renderer *renderer = list->data;
+
+ gtk_widget_queue_draw (GTK_WIDGET (renderer->renderer));
+ }
+}
+
+static GtkAdjustment *
+get_adjustment (GtkSourceGutter *gutter,
+ GtkSourceView *view)
+{
+ if (gutter->window_type == GTK_TEXT_WINDOW_LEFT ||
+ gutter->window_type == GTK_TEXT_WINDOW_RIGHT)
+ {
+ return gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (view));
+ }
+ else
+ {
+ return gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (view));
+ }
+}
+
+static void
+connect_view (GtkSourceGutter *gutter,
+ GtkSourceView *view)
+{
+ g_assert (GTK_SOURCE_IS_GUTTER (gutter));
+ g_assert (GTK_SOURCE_IS_VIEW (view));
+
+ gutter->adj_changed_handler =
+ g_signal_connect (get_adjustment (gutter, view),
+ "value-changed",
+ G_CALLBACK (on_adjustment_value_changed),
+ gutter);
+
+ gutter->style_updated_handler =
+ g_signal_connect (view,
+ "style-updated",
+ G_CALLBACK (on_view_style_updated),
+ gutter);
+}
+
+static void
+disconnect_view (GtkSourceGutter *gutter,
+ GtkSourceView *view)
{
- update_gutter_size (gutter);
+ g_assert (GTK_SOURCE_IS_GUTTER (gutter));
+ g_assert (GTK_SOURCE_IS_VIEW (view));
+
+ g_clear_signal_handler (&gutter->adj_changed_handler,
+ get_adjustment (gutter, view));
+ g_clear_signal_handler (&gutter->realize_handler, view);
+ g_clear_signal_handler (&gutter->style_updated_handler, view);
}
static void
set_view (GtkSourceGutter *gutter,
GtkSourceView *view)
{
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
+ g_return_if_fail (!view || GTK_SOURCE_IS_VIEW (view));
+
+ if (view == gutter->view)
+ {
+ return;
+ }
+
+ if (gutter->view != NULL)
+ {
+ disconnect_view (gutter, gutter->view);
+ }
+
gutter->view = view;
- g_signal_connect_object (view,
- "motion-notify-event",
- G_CALLBACK (on_view_motion_notify_event),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "enter-notify-event",
- G_CALLBACK (on_view_enter_notify_event),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "leave-notify-event",
- G_CALLBACK (on_view_leave_notify_event),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "button-press-event",
- G_CALLBACK (on_view_button_press_event),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "query-tooltip",
- G_CALLBACK (on_view_query_tooltip),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "realize",
- G_CALLBACK (on_view_realize),
- gutter,
- 0);
-
- g_signal_connect_object (view,
- "style-updated",
- G_CALLBACK (on_view_style_updated),
- gutter,
- 0);
+ if (view != NULL)
+ {
+ connect_view (gutter, view);
+ }
}
static void
do_redraw (GtkSourceGutter *gutter)
{
- GdkWindow *window;
-
- window = gtk_text_view_get_window (GTK_TEXT_VIEW (gutter->view),
- gutter->window_type);
-
- if (window && !gutter->is_drawing)
+ if (!gutter->is_drawing)
{
- gdk_window_invalidate_rect (window, NULL, FALSE);
+ gtk_widget_queue_draw (GTK_WIDGET (gutter));
}
}
-static gint
-calculate_gutter_size (GtkSourceGutter *gutter,
- GArray *sizes)
+static void
+gtk_source_gutter_map (GtkWidget *widget)
+{
+ gtk_widget_set_cursor_from_name (widget, "arrow");
+ GTK_WIDGET_CLASS (gtk_source_gutter_parent_class)->map (widget);
+}
+
+static void
+gtk_source_gutter_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
{
- GList *item;
- gint total_width = 0;
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (widget);
+ const GList *item;
/* Calculate size */
- for (item = gutter->renderers; item; item = g_list_next (item))
+ for (item = gutter->renderers; item; item = item->next)
{
Renderer *renderer = item->data;
- gint width;
+ int r_minimum;
+ int r_natural;
+ int r_minimum_baseline;
+ int r_natural_baseline;
- if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
+ if (!gtk_widget_get_visible (GTK_WIDGET (renderer->renderer)))
{
- width = 0;
+ continue;
}
- else
- {
- gint xpad;
- gint size;
- size = gtk_source_gutter_renderer_get_size (renderer->renderer);
+ gtk_widget_measure (GTK_WIDGET (renderer->renderer),
+ orientation,
+ for_size,
+ &r_minimum,
+ &r_natural,
+ &r_minimum_baseline,
+ &r_natural_baseline);
- gtk_source_gutter_renderer_get_padding (renderer->renderer,
- &xpad,
- NULL);
+ *minimum += r_minimum;
+ *natural += r_natural;
+ }
- width = size + 2 * xpad;
- }
+ *minimum_baseline = -1;
+ *natural_baseline = -1;
+}
- if (sizes)
- {
- g_array_append_val (sizes, width);
- }
+static void
+apply_style (GtkSourceGutter *gutter,
+ GtkStyleContext *style_context)
+{
+ const gchar *class;
+
+ switch (gutter->window_type)
+ {
+ case GTK_TEXT_WINDOW_TOP:
+ class = GTK_STYLE_CLASS_TOP;
+ break;
+
+ case GTK_TEXT_WINDOW_RIGHT:
+ class = GTK_STYLE_CLASS_RIGHT;
+ break;
+
+ case GTK_TEXT_WINDOW_BOTTOM:
+ class = GTK_STYLE_CLASS_BOTTOM;
+ break;
+
+ case GTK_TEXT_WINDOW_LEFT:
+ class = GTK_STYLE_CLASS_LEFT;
+ break;
- total_width += width;
+ case GTK_TEXT_WINDOW_WIDGET:
+ case GTK_TEXT_WINDOW_TEXT:
+ default:
+ g_return_if_reached ();
}
- return total_width;
+ gtk_style_context_add_class (style_context, class);
+}
+
+static void
+gtk_source_gutter_root (GtkWidget *widget)
+{
+ GtkWidget *view;
+
+ GTK_WIDGET_CLASS (gtk_source_gutter_parent_class)->root (widget);
+
+ view = gtk_widget_get_ancestor (widget, GTK_SOURCE_TYPE_VIEW);
+ set_view (GTK_SOURCE_GUTTER (widget), GTK_SOURCE_VIEW (view));
+}
+
+static void
+gtk_source_gutter_unroot (GtkWidget *widget)
+{
+ GTK_WIDGET_CLASS (gtk_source_gutter_parent_class)->unroot (widget);
+ set_view (GTK_SOURCE_GUTTER (widget), NULL);
}
static void
-update_gutter_size (GtkSourceGutter *gutter)
+gtk_source_gutter_forall (GtkContainer *container,
+ GtkCallback callback,
+ gpointer callback_data)
{
- gint width = calculate_gutter_size (gutter, NULL);
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (container);
+ const GList *list = gutter->renderers;
+
+ while (list != NULL)
+ {
+ Renderer *renderer = list->data;
+
+ list = list->next;
- gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (gutter->view),
- gutter->window_type,
- width);
+ callback (GTK_WIDGET (renderer->renderer), callback_data);
+ }
}
static void
-gtk_source_gutter_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_source_gutter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- GtkSourceGutter *self = GTK_SOURCE_GUTTER (object);
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (object);
switch (prop_id)
{
- case PROP_VIEW:
- set_view (self, GTK_SOURCE_VIEW (g_value_get_object (value)));
- break;
case PROP_WINDOW_TYPE:
- self->window_type = g_value_get_enum (value);
+ gutter->window_type = g_value_get_enum (value);
break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -402,33 +430,48 @@ gtk_source_gutter_set_property (GObject *object,
static void
gtk_source_gutter_constructed (GObject *object)
{
- GtkSourceGutter *gutter;
-
- gutter = GTK_SOURCE_GUTTER (object);
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (object);
+ GtkStyleContext *context;
if (gutter->window_type == GTK_TEXT_WINDOW_LEFT ||
gutter->window_type == GTK_TEXT_WINDOW_RIGHT)
{
gutter->orientation = GTK_ORIENTATION_HORIZONTAL;
+ gtk_widget_set_vexpand (GTK_WIDGET (gutter), TRUE);
}
else
{
gutter->orientation = GTK_ORIENTATION_VERTICAL;
+ gtk_widget_set_hexpand (GTK_WIDGET (gutter), TRUE);
}
G_OBJECT_CLASS (gtk_source_gutter_parent_class)->constructed (object);
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (gutter));
+ apply_style (gutter, context);
}
static void
gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
- object_class->set_property = gtk_source_gutter_set_property;
+ object_class->constructed = gtk_source_gutter_constructed;
object_class->get_property = gtk_source_gutter_get_property;
+ object_class->set_property = gtk_source_gutter_set_property;
- object_class->dispose = gtk_source_gutter_dispose;
- object_class->constructed = gtk_source_gutter_constructed;
+ widget_class->map = gtk_source_gutter_map;
+ widget_class->measure = gtk_source_gutter_measure;
+ widget_class->root = gtk_source_gutter_root;
+ widget_class->size_allocate = gtk_source_gutter_size_allocate;
+ widget_class->snapshot = gtk_source_gutter_snapshot;
+ widget_class->unroot = gtk_source_gutter_unroot;
+
+ container_class->forall = gtk_source_gutter_forall;
+ container_class->add = gtk_source_gutter_add;
+ container_class->remove = gtk_source_gutter_remove;
/**
* GtkSourceGutter:view:
@@ -441,7 +484,7 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
"View",
"",
GTK_SOURCE_TYPE_VIEW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GtkSourceGutter:window-type:
@@ -454,14 +497,43 @@ gtk_source_gutter_class_init (GtkSourceGutterClass *klass)
"Window Type",
"The gutters' text window type",
GTK_TYPE_TEXT_WINDOW_TYPE,
- 0,
+ GTK_TEXT_WINDOW_LEFT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ gtk_widget_class_set_css_name (widget_class, "gutter");
}
static void
-gtk_source_gutter_init (GtkSourceGutter *self)
+gtk_source_gutter_init (GtkSourceGutter *gutter)
{
- self = gtk_source_gutter_get_instance_private (self);
+ GtkGesture *click;
+ GtkEventController *motion;
+
+ gutter->window_type = GTK_TEXT_WINDOW_LEFT;
+
+ /* Setup fallback click handling */
+ click = gtk_gesture_click_new ();
+ g_signal_connect_swapped (click,
+ "pressed",
+ G_CALLBACK (on_gutter_pressed_cb),
+ gutter);
+ gtk_widget_add_controller (GTK_WIDGET (gutter), GTK_EVENT_CONTROLLER (click));
+
+ /* Track motion enter/leave for prelit status */
+ motion = gtk_event_controller_motion_new ();
+ g_signal_connect_swapped (motion,
+ "enter",
+ G_CALLBACK (gtk_widget_queue_draw),
+ gutter);
+ g_signal_connect_swapped (motion,
+ "leave",
+ G_CALLBACK (gtk_widget_queue_draw),
+ gutter);
+ g_signal_connect_swapped (motion,
+ "motion",
+ G_CALLBACK (gtk_widget_queue_draw),
+ gutter);
+ gtk_widget_add_controller (GTK_WIDGET (gutter), motion);
}
static gint
@@ -487,32 +559,26 @@ static void
append_renderer (GtkSourceGutter *gutter,
Renderer *renderer)
{
- gutter->renderers =
- g_list_insert_sorted_with_data (gutter->renderers,
- renderer,
- (GCompareDataFunc)sort_by_position,
- NULL);
-
- update_gutter_size (gutter);
+ gutter->renderers = g_list_insert_sorted_with_data (gutter->renderers,
+ renderer,
+ (GCompareDataFunc)sort_by_position,
+ NULL);
}
GtkSourceGutter *
-_gtk_source_gutter_new (GtkSourceView *view,
- GtkTextWindowType type)
+_gtk_source_gutter_new (GtkTextWindowType type)
{
return g_object_new (GTK_SOURCE_TYPE_GUTTER,
- "view", view,
"window_type", type,
NULL);
}
-/* Public API */
-
/**
* gtk_source_gutter_get_view:
* @gutter: a #GtkSourceGutter.
*
* Returns: (transfer none): the associated #GtkSourceView.
+ *
* Since: 3.24
*/
GtkSourceView *
@@ -523,21 +589,6 @@ gtk_source_gutter_get_view (GtkSourceGutter *gutter)
return gutter->view;
}
-/**
- * gtk_source_gutter_get_window_type:
- * @gutter: a #GtkSourceGutter.
- *
- * Returns: the #GtkTextWindowType of @gutter.
- * Since: 3.24
- */
-GtkTextWindowType
-gtk_source_gutter_get_window_type (GtkSourceGutter *gutter)
-{
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), GTK_TEXT_WINDOW_PRIVATE);
-
- return gutter->window_type;
-}
-
/**
* gtk_source_gutter_insert:
* @gutter: a #GtkSourceGutter.
@@ -563,10 +614,11 @@ gtk_source_gutter_insert (GtkSourceGutter *gutter,
g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), FALSE);
g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), FALSE);
g_return_val_if_fail (gtk_source_gutter_renderer_get_view (renderer) == NULL, FALSE);
- g_return_val_if_fail (gtk_source_gutter_renderer_get_window_type (renderer) ==
GTK_TEXT_WINDOW_PRIVATE, FALSE);
internal_renderer = renderer_new (gutter, renderer, position);
append_renderer (gutter, internal_renderer);
+ gtk_widget_set_parent (GTK_WIDGET (renderer), GTK_WIDGET (gutter));
+ gtk_widget_queue_resize (GTK_WIDGET (gutter));
return TRUE;
}
@@ -579,7 +631,7 @@ renderer_find (GtkSourceGutter *gutter,
{
GList *list;
- for (list = gutter->renderers; list; list = g_list_next (list))
+ for (list = gutter->renderers; list; list = list->next)
{
*ret = list->data;
@@ -597,6 +649,55 @@ renderer_find (GtkSourceGutter *gutter,
return FALSE;
}
+static void
+gtk_source_gutter_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ if (!GTK_SOURCE_IS_GUTTER_RENDERER (widget))
+ {
+ g_warning ("Cannot add %s to %s as it is not a GtkSourceGutterRenderer",
+ G_OBJECT_TYPE_NAME (widget),
+ G_OBJECT_TYPE_NAME (container));
+ }
+ else
+ {
+ gtk_source_gutter_insert (GTK_SOURCE_GUTTER (container),
+ GTK_SOURCE_GUTTER_RENDERER (widget),
+ 0);
+ }
+}
+
+static void
+gtk_source_gutter_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkSourceGutterRenderer *renderer;
+ GtkSourceGutter *gutter;
+ Renderer *ret;
+ GList *retlist;
+
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER (container));
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (widget));
+
+ gutter = GTK_SOURCE_GUTTER (container);
+ renderer = GTK_SOURCE_GUTTER_RENDERER (widget);
+
+ if (renderer_find (gutter, renderer, &ret, &retlist))
+ {
+ gutter->renderers =
+ g_list_delete_link (gutter->renderers, retlist);
+ gtk_widget_unparent (GTK_WIDGET (renderer));
+ renderer_free (ret);
+ gtk_widget_queue_resize (GTK_WIDGET (gutter));
+ }
+ else
+ {
+ g_warning ("Failed to locate %s within %s",
+ G_OBJECT_TYPE_NAME (widget),
+ G_OBJECT_TYPE_NAME (gutter));
+ }
+}
+
/**
* gtk_source_gutter_reorder:
* @gutter: a #GtkSourceGutterRenderer.
@@ -621,629 +722,201 @@ gtk_source_gutter_reorder (GtkSourceGutter *gutter,
if (renderer_find (gutter, renderer, &ret, &retlist))
{
gutter->renderers =
- g_list_delete_link (gutter->renderers,
- retlist);
-
+ g_list_delete_link (gutter->renderers, retlist);
ret->position = position;
append_renderer (gutter, ret);
+ gtk_widget_queue_allocate (GTK_WIDGET (gutter));
}
}
-/**
- * gtk_source_gutter_remove:
- * @gutter: a #GtkSourceGutter.
- * @renderer: a #GtkSourceGutterRenderer.
- *
- * Removes @renderer from @gutter.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_remove (GtkSourceGutter *gutter,
- GtkSourceGutterRenderer *renderer)
+static void
+gtk_source_gutter_size_allocate (GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
{
- Renderer *ret;
- GList *retlist;
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (widget);
+ const GList *list;
+ gint x = 0;
- g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ GTK_WIDGET_CLASS (gtk_source_gutter_parent_class)->size_allocate (widget,
+ width,
+ height,
+ baseline);
- if (renderer_find (gutter, renderer, &ret, &retlist))
+ for (list = gutter->renderers; list; list = list->next)
{
- gutter->renderers =
- g_list_delete_link (gutter->renderers,
- retlist);
+ Renderer *renderer = list->data;
+ GtkRequisition child_req;
+ GtkAllocation alloc;
- update_gutter_size (gutter);
- renderer_free (ret);
- }
-}
+ gtk_widget_get_preferred_size (GTK_WIDGET (renderer->renderer),
+ &child_req, NULL);
-/**
- * gtk_source_gutter_queue_draw:
- * @gutter: a #GtkSourceGutter.
- *
- * Invalidates the drawable area of the gutter. You can use this to force a
- * redraw of the gutter if something has changed and needs to be redrawn.
- *
- * Since: 2.8
- */
-void
-gtk_source_gutter_queue_draw (GtkSourceGutter *gutter)
-{
- g_return_if_fail (GTK_SOURCE_IS_GUTTER (gutter));
+ alloc.x = x;
+ alloc.y = 0;
+ alloc.width = child_req.width;
+ alloc.height = height;
- do_redraw (gutter);
+ gtk_widget_size_allocate (GTK_WIDGET (renderer->renderer),
+ &alloc,
+ -1);
+
+ x += alloc.width;
+ }
+
+ gtk_widget_queue_draw (widget);
}
-typedef struct
+static void
+gtk_source_gutter_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
- gint total_height;
- gint lines_count;
- GArray *buffer_coords;
- GArray *line_heights;
- GArray *line_numbers;
- GtkTextIter start;
+ GtkSourceGutter *gutter = GTK_SOURCE_GUTTER (widget);
+ GtkTextView *text_view = GTK_TEXT_VIEW (gutter->view);
+ GtkStyleContext *view_context;
+ const GList *list;
+ GdkRectangle visible_rect;
+ GtkTextIter begin;
GtkTextIter end;
-} LinesInfo;
+ gboolean needs_wrap_first = FALSE;
+ gboolean needs_wrap_last = FALSE;
-static LinesInfo *
-lines_info_new (void)
-{
- LinesInfo *info;
+ g_clear_object (&gutter->lines);
- info = g_slice_new0 (LinesInfo);
+ if (text_view == NULL || gtk_widget_get_width (widget) == 0)
+ {
+ return;
+ }
- info->buffer_coords = g_array_new (FALSE, FALSE, sizeof (gint));
- info->line_heights = g_array_new (FALSE, FALSE, sizeof (gint));
- info->line_numbers = g_array_new (FALSE, FALSE, sizeof (gint));
+ /* We need the style from the view itself for highlight lines */
+ view_context = gtk_widget_get_style_context (GTK_WIDGET (gutter->view));
- return info;
-}
+ gtk_text_view_get_visible_rect (text_view, &visible_rect);
+ gtk_text_view_get_iter_at_location (text_view, &begin,
+ visible_rect.x, visible_rect.y);
+ gtk_text_view_get_iter_at_location (text_view, &end,
+ visible_rect.x,
+ visible_rect.y + visible_rect.height);
-static void
-lines_info_free (LinesInfo *info)
-{
- if (info != NULL)
+ /* The first step is to get line information about all the visible
+ * lines. We do this up front so that we can do it once to reduce many
+ * times the renderers need to walk through the buffer contents as that
+ * can be expensive.
+ */
+ get_alignment_modes (gutter, &needs_wrap_first, &needs_wrap_last);
+ gutter->lines = _gtk_source_gutter_lines_new (text_view,
+ &begin,
+ &end,
+ needs_wrap_first,
+ needs_wrap_last);
+
+ /* Draw the current-line highlight if necessary */
+ if (gtk_source_view_get_highlight_current_line (gutter->view))
{
- g_array_free (info->buffer_coords, TRUE);
- g_array_free (info->line_heights, TRUE);
- g_array_free (info->line_numbers, TRUE);
+ guint cursor_line;
- g_slice_free (LinesInfo, info);
- }
-}
+ cursor_line = _gtk_source_gutter_lines_get_cursor_line (gutter->lines);
-/* This function is taken and adapted from gtk+/tests/testtext.c */
-static LinesInfo *
-get_lines_info (GtkTextView *text_view,
- gint first_y_buffer_coord,
- gint last_y_buffer_coord)
-{
- LinesInfo *info;
- GtkTextIter iter;
- gint last_line_num = -1;
+ if (cursor_line >= gtk_source_gutter_lines_get_first (gutter->lines) &&
+ cursor_line <= gtk_source_gutter_lines_get_last (gutter->lines))
+ {
+ gint y;
+ gint height;
+
+ gtk_source_gutter_lines_get_line_yrange (gutter->lines,
+ cursor_line,
+
GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+ &y,
+ &height);
+
+ gtk_style_context_save (view_context);
+ gtk_style_context_add_class (view_context, "current-line-number");
+
+ gtk_snapshot_render_background (snapshot,
+ view_context,
+ 0,
+ y,
+ gtk_widget_get_width (widget),
+ height);
+
+ gtk_style_context_restore (view_context);
+ }
+ }
- info = lines_info_new ();
+ gutter->is_drawing = TRUE;
- /* Get iter at first y */
- gtk_text_view_get_line_at_y (text_view, &iter, first_y_buffer_coord, NULL);
+ /* Now let the renderers populate information about the lines that are
+ * to be rendered. They may need to go through line by line and add
+ * classes (GQuark) to the lines to be used when snapshoting. Since
+ * we've already calculated line information, this is relatively fast.
+ *
+ * We also only emit the ::query-data signal in the case that the
+ * renderer has not override then (*query_data) vfunc which saves quite
+ * a bit of signal overhead.
+ */
+ for (list = gutter->renderers; list; list = list->next)
+ {
+ Renderer *renderer = list->data;
- info->start = iter;
+ _gtk_source_gutter_renderer_begin (renderer->renderer,
+ gutter->lines);
+ }
- /* For each iter, get its location and add it to the arrays.
- * Stop when we pass last_y_buffer_coord.
+ gtk_snapshot_push_clip (snapshot,
+ &GRAPHENE_RECT_INIT (0,
+ 0,
+ gtk_widget_get_width (widget),
+ gtk_widget_get_height (widget)));
+
+ /* Now let the renderers draw the content for each line. Because
+ * iterating a Linked-List is slower than iterating a series of line
+ * numbers, we make the renderer list the outter loop, and the
+ * snapshotting of lines (within the renderer) the inner loop as part
+ * of snapshot.
*/
- while (!gtk_text_iter_is_end (&iter))
+ for (list = gutter->renderers; list; list = list->next)
{
- gint y;
- gint height;
- gint line_num;
+ Renderer *renderer = list->data;
- gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
-
- g_array_append_val (info->buffer_coords, y);
- g_array_append_val (info->line_heights, height);
+ gtk_widget_snapshot_child (widget,
+ GTK_WIDGET (renderer->renderer),
+ snapshot);
+ }
- info->total_height += height;
+ gtk_snapshot_pop (snapshot);
- line_num = gtk_text_iter_get_line (&iter);
- g_array_append_val (info->line_numbers, line_num);
+ /* Allow to call queue_redraw() in end. */
+ gutter->is_drawing = FALSE;
- last_line_num = line_num;
+ /* Now notify the renderers of completion */
+ for (list = gutter->renderers; list; list = list->next)
+ {
+ Renderer *renderer = list->data;
- info->lines_count++;
-
- if (last_y_buffer_coord <= (y + height))
- {
- break;
- }
-
- gtk_text_iter_forward_line (&iter);
- }
-
- if (gtk_text_iter_is_end (&iter))
- {
- gint y;
- gint height;
- gint line_num;
-
- gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
-
- line_num = gtk_text_iter_get_line (&iter);
-
- if (line_num != last_line_num)
- {
- g_array_append_val (info->buffer_coords, y);
- g_array_append_val (info->line_heights, height);
-
- info->total_height += height;
-
- g_array_append_val (info->line_numbers, line_num);
- info->lines_count++;
- }
- }
-
- if (info->lines_count == 0)
- {
- gint y = 0;
- gint n = 0;
- gint height;
-
- info->lines_count = 1;
-
- g_array_append_val (info->buffer_coords, y);
- g_array_append_val (info->line_numbers, n);
-
- gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
- g_array_append_val (info->line_heights, height);
-
- info->total_height += height;
- }
-
- info->end = iter;
-
- return info;
-}
-
-/* Returns %TRUE if @clip is set. @clip contains the area that should be drawn. */
-static gboolean
-get_clip_rectangle (GtkSourceGutter *gutter,
- GtkSourceView *view,
- cairo_t *cr,
- GdkRectangle *clip)
-{
- GdkWindow *window = get_window (gutter);
-
- if (window == NULL || !gtk_cairo_should_draw_window (cr, window))
- {
- return FALSE;
- }
-
- gtk_cairo_transform_to_window (cr, GTK_WIDGET (view), window);
-
- return gdk_cairo_get_clip_rectangle (cr, clip);
-}
-
-static void
-apply_style (GtkSourceGutter *gutter,
- GtkSourceView *view,
- GtkStyleContext *style_context,
- cairo_t *cr)
-{
- const gchar *class;
- GdkRGBA fg_color;
-
- switch (gutter->window_type)
- {
- case GTK_TEXT_WINDOW_TOP:
- class = GTK_STYLE_CLASS_TOP;
- break;
-
- case GTK_TEXT_WINDOW_RIGHT:
- class = GTK_STYLE_CLASS_RIGHT;
- break;
-
- case GTK_TEXT_WINDOW_BOTTOM:
- class = GTK_STYLE_CLASS_BOTTOM;
- break;
-
- case GTK_TEXT_WINDOW_LEFT:
- class = GTK_STYLE_CLASS_LEFT;
- break;
-
- case GTK_TEXT_WINDOW_PRIVATE:
- case GTK_TEXT_WINDOW_WIDGET:
- case GTK_TEXT_WINDOW_TEXT:
- default:
- g_return_if_reached ();
- }
-
- /* Apply classes ourselves, since we are in connect_after and so they
- * are not set by gtk.
- */
- gtk_style_context_add_class (style_context, class);
- gtk_style_context_get_color (style_context,
- gtk_style_context_get_state (style_context),
- &fg_color);
-
- gdk_cairo_set_source_rgba (cr, &fg_color);
-}
-
-/* Call gtk_source_gutter_renderer_begin() on each renderer. */
-static void
-begin_draw (GtkSourceGutter *gutter,
- GtkTextView *view,
- GArray *renderer_widths,
- LinesInfo *info,
- cairo_t *cr)
-{
- GdkRectangle background_area = { 0 };
- GdkRectangle cell_area;
- GList *l;
- gint renderer_num;
-
- background_area.x = 0;
- background_area.height = info->total_height;
-
- gtk_text_view_buffer_to_window_coords (view,
- gutter->window_type,
- 0,
- g_array_index (info->buffer_coords, gint, 0),
- NULL,
- &background_area.y);
-
- cell_area = background_area;
-
- for (l = gutter->renderers, renderer_num = 0;
- l != NULL;
- l = l->next, renderer_num++)
- {
- Renderer *renderer = l->data;
- gint width;
- gint xpad;
-
- width = g_array_index (renderer_widths, gint, renderer_num);
-
- if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
- {
- g_assert_cmpint (width, ==, 0);
- continue;
- }
-
- gtk_source_gutter_renderer_get_padding (renderer->renderer,
- &xpad,
- NULL);
-
- background_area.width = width;
-
- cell_area.width = background_area.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,
- &info->start,
- &info->end);
-
- cairo_restore (cr);
-
- background_area.x += background_area.width;
- }
-}
-
-static void
-draw_cells (GtkSourceGutter *gutter,
- GtkTextView *view,
- GArray *renderer_widths,
- LinesInfo *info,
- cairo_t *cr)
-{
- GtkTextBuffer *buffer;
- GtkTextIter insert_iter;
- gint cur_line;
- GtkTextIter selection_start;
- GtkTextIter selection_end;
- gint selection_start_line = 0;
- gint selection_end_line = 0;
- gboolean has_selection;
- GtkTextIter start;
- gint i;
-
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_mark (buffer,
- &insert_iter,
- gtk_text_buffer_get_insert (buffer));
-
- cur_line = gtk_text_iter_get_line (&insert_iter);
-
- has_selection = gtk_text_buffer_get_selection_bounds (buffer,
- &selection_start,
- &selection_end);
-
- if (has_selection)
- {
- selection_start_line = gtk_text_iter_get_line (&selection_start);
- selection_end_line = gtk_text_iter_get_line (&selection_end);
- }
-
- start = info->start;
- i = 0;
-
- while (i < info->lines_count)
- {
- GtkTextIter end;
- GdkRectangle background_area;
- GtkSourceGutterRendererState state;
- gint pos;
- gint line_to_paint;
- gint renderer_num;
- GList *l;
-
- end = start;
-
- if (!gtk_text_iter_ends_line (&end))
- {
- /*
- * It turns out that gtk_text_iter_forward_to_line_end
- * is slower than jumping to the next line in the
- * btree index and then moving backwards a character.
- * We don't really care that we might be after the
- * newline breaking characters, since those are part
- * of the same line (rather than the next line).
- */
- if (gtk_text_iter_forward_line (&end))
- {
- gtk_text_iter_backward_char (&end);
- }
- }
-
- /* Possible improvement: if buffer and window coords have the
- * same unit, there are probably some possible performance
- * improvements by avoiding some buffer <-> window coords
- * conversions.
- */
- gtk_text_view_buffer_to_window_coords (view,
- gutter->window_type,
- 0,
- g_array_index (info->buffer_coords, gint, i),
- NULL,
- &pos);
-
- line_to_paint = g_array_index (info->line_numbers, gint, i);
-
- background_area.y = pos;
- background_area.height = g_array_index (info->line_heights, gint, i);
- background_area.x = 0;
-
- state = GTK_SOURCE_GUTTER_RENDERER_STATE_NORMAL;
-
- if (line_to_paint == cur_line)
- {
- state |= GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR;
- }
-
- if (has_selection &&
- selection_start_line <= line_to_paint && line_to_paint <= selection_end_line)
- {
- state |= GTK_SOURCE_GUTTER_RENDERER_STATE_SELECTED;
- }
-
- for (l = gutter->renderers, renderer_num = 0;
- l != NULL;
- l = l->next, renderer_num++)
- {
- Renderer *renderer;
- GdkRectangle cell_area;
- gint width;
- gint xpad;
- gint ypad;
-
- renderer = l->data;
- width = g_array_index (renderer_widths, gint, renderer_num);
-
- if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
- {
- g_assert_cmpint (width, ==, 0);
- continue;
- }
-
- gtk_source_gutter_renderer_get_padding (renderer->renderer,
- &xpad,
- &ypad);
-
- background_area.width = width;
-
- cell_area.y = background_area.y + ypad;
- cell_area.height = background_area.height - 2 * ypad;
-
- cell_area.x = background_area.x + xpad;
- cell_area.width = background_area.width - 2 * xpad;
-
- if (renderer->prelit >= 0 &&
- cell_area.y <= renderer->prelit && renderer->prelit <= cell_area.y +
cell_area.height)
- {
- 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;
- state &= ~GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT;
- }
-
- i++;
- gtk_text_iter_forward_line (&start);
- }
-}
-
-static void
-end_draw (GtkSourceGutter *gutter)
-{
- GList *l;
-
- for (l = gutter->renderers; l != NULL; l = l->next)
- {
- Renderer *renderer = l->data;
-
- if (gtk_source_gutter_renderer_get_visible (renderer->renderer))
- {
- gtk_source_gutter_renderer_end (renderer->renderer);
- }
+ _gtk_source_gutter_renderer_end (renderer->renderer);
}
}
-void
-_gtk_source_gutter_draw (GtkSourceGutter *gutter,
- GtkSourceView *view,
- cairo_t *cr)
-{
- GdkRectangle clip;
- GtkTextView *text_view;
- gint first_y_window_coord;
- gint last_y_window_coord;
- gint first_y_buffer_coord;
- gint last_y_buffer_coord;
- GArray *renderer_widths;
- LinesInfo *info;
- GtkStyleContext *style_context;
-
- if (!get_clip_rectangle (gutter, view, cr, &clip))
- {
- return;
- }
-
- gutter->is_drawing = TRUE;
-
- renderer_widths = g_array_new (FALSE, FALSE, sizeof (gint));
- calculate_gutter_size (gutter, renderer_widths);
-
- text_view = GTK_TEXT_VIEW (view);
-
- first_y_window_coord = clip.y;
- last_y_window_coord = first_y_window_coord + clip.height;
-
- /* get the extents of the line printing */
- gtk_text_view_window_to_buffer_coords (text_view,
- gutter->window_type,
- 0,
- first_y_window_coord,
- NULL,
- &first_y_buffer_coord);
-
- gtk_text_view_window_to_buffer_coords (text_view,
- gutter->window_type,
- 0,
- last_y_window_coord,
- NULL,
- &last_y_buffer_coord);
-
- info = get_lines_info (text_view,
- first_y_buffer_coord,
- last_y_buffer_coord);
-
- style_context = gtk_widget_get_style_context (GTK_WIDGET (view));
- gtk_style_context_save (style_context);
- apply_style (gutter, view, style_context, cr);
-
- begin_draw (gutter,
- text_view,
- renderer_widths,
- info,
- cr);
-
- draw_cells (gutter,
- text_view,
- renderer_widths,
- info,
- cr);
-
- /* Allow to call queue_redraw() in ::end. */
- gutter->is_drawing = FALSE;
-
- end_draw (gutter);
-
- gtk_style_context_restore (style_context);
-
- g_array_free (renderer_widths, TRUE);
- lines_info_free (info);
-}
-
static Renderer *
renderer_at_x (GtkSourceGutter *gutter,
gint x,
- gint *start,
gint *width)
{
- GList *item;
- gint s;
- gint w;
-
- update_gutter_size (gutter);
-
- s = 0;
+ const GList *item;
for (item = gutter->renderers; item; item = g_list_next (item))
{
Renderer *renderer = item->data;
- gint xpad;
+ GtkAllocation alloc;
- if (!gtk_source_gutter_renderer_get_visible (renderer->renderer))
- {
- continue;
- }
+ gtk_widget_get_allocation (GTK_WIDGET (renderer->renderer),
+ &alloc);
- w = gtk_source_gutter_renderer_get_size (renderer->renderer);
-
- gtk_source_gutter_renderer_get_padding (renderer->renderer,
- &xpad,
- NULL);
-
- s += xpad;
-
- if (w > 0 && x >= s && x < s + w)
+ if (x >= alloc.x && x <= alloc.x + alloc.width)
{
- if (width)
- {
- *width = w;
- }
-
- if (start)
- {
- *start = s;
- }
-
return renderer;
}
-
- s += w + xpad;
}
return NULL;
@@ -1254,21 +927,18 @@ get_renderer_rect (GtkSourceGutter *gutter,
Renderer *renderer,
GtkTextIter *iter,
gint line,
- GdkRectangle *rectangle,
- gint start)
+ GdkRectangle *rectangle)
{
gint y;
gint ypad;
- rectangle->x = start;
+ gtk_widget_get_allocation (GTK_WIDGET (renderer->renderer), rectangle);
gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (gutter->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->view),
gutter->window_type,
0,
@@ -1276,9 +946,7 @@ get_renderer_rect (GtkSourceGutter *gutter,
NULL,
&rectangle->y);
- gtk_source_gutter_renderer_get_padding (renderer->renderer,
- NULL,
- &ypad);
+ ypad = gtk_source_gutter_renderer_get_ypad (renderer->renderer);
rectangle->y += ypad;
rectangle->height -= 2 * ypad;
@@ -1287,27 +955,25 @@ get_renderer_rect (GtkSourceGutter *gutter,
static gboolean
renderer_query_activatable (GtkSourceGutter *gutter,
Renderer *renderer,
- GdkEvent *event,
- gint x,
- gint y,
+ gdouble x,
+ gdouble y,
GtkTextIter *line_iter,
- GdkRectangle *rect,
- gint start)
+ GdkRectangle *rect)
{
gint y_buf;
gint yline;
GtkTextIter iter;
- GdkRectangle r;
+ GdkRectangle r = {0};
- if (!renderer)
+ if (renderer == NULL)
{
return FALSE;
}
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (gutter->view),
- gutter->window_type,
- x,
- y,
+ GTK_TEXT_WINDOW_WIDGET,
+ (gint)x,
+ (gint)y,
NULL,
&y_buf);
@@ -1321,7 +987,7 @@ renderer_query_activatable (GtkSourceGutter *gutter,
return FALSE;
}
- get_renderer_rect (gutter, renderer, &iter, yline, &r, start);
+ get_renderer_rect (gutter, renderer, &iter, yline, &r);
if (line_iter)
{
@@ -1338,259 +1004,81 @@ renderer_query_activatable (GtkSourceGutter *gutter,
return FALSE;
}
- return gtk_source_gutter_renderer_query_activatable (renderer->renderer,
- &iter,
- &r,
- event);
+ return gtk_source_gutter_renderer_query_activatable (renderer->renderer, &iter, &r);
}
-static gboolean
-redraw_for_window (GtkSourceGutter *gutter,
- GdkEvent *event,
- gboolean act_on_window,
- gint x,
- gint y)
-{
- Renderer *at_x = NULL;
- gint start = 0;
- GList *item;
- gboolean redraw;
-
- if (event->any.window != get_window (gutter) && act_on_window)
- {
- return FALSE;
- }
-
- if (act_on_window)
- {
- at_x = renderer_at_x (gutter, x, &start, NULL);
- }
-
- redraw = FALSE;
-
- for (item = gutter->renderers; item; item = g_list_next (item))
- {
- 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,
- 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,
- (GdkEvent *)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,
- (GdkEvent *)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,
- (GdkEvent *)event,
- FALSE,
- (gint)event->x,
- (gint)event->y);
-}
-
-static gboolean
-on_view_button_press_event (GtkSourceView *view,
- GdkEventButton *event,
- GtkSourceGutter *gutter)
+static void
+on_gutter_pressed_cb (GtkSourceGutter *gutter,
+ gint n_presses,
+ gdouble x,
+ gdouble y,
+ GtkGestureClick *click)
{
+ const GdkEvent *last_event;
Renderer *renderer;
GtkTextIter line_iter;
- gint start = -1;
GdkRectangle rect;
+ GdkModifierType state;
+ guint button;
- if (event->window != get_window (gutter))
- {
- return FALSE;
- }
+ g_assert (GTK_SOURCE_IS_GUTTER (gutter));
+ g_assert (GTK_IS_GESTURE_CLICK (click));
+
+ last_event = gtk_gesture_get_last_event (GTK_GESTURE (click), NULL);
- if (event->type != GDK_BUTTON_PRESS)
+ if (last_event == NULL ||
+ !gdk_event_get_state (last_event, &state) ||
+ !gdk_event_get_button (last_event, &button))
{
- return FALSE;
+ return;
}
/* Check cell renderer */
- renderer = renderer_at_x (gutter, event->x, &start, NULL);
+ renderer = renderer_at_x (gutter, x, NULL);
if (renderer_query_activatable (gutter,
renderer,
- (GdkEvent *)event,
- (gint)event->x,
- (gint)event->y,
+ x,
+ y,
&line_iter,
- &rect,
- start))
+ &rect))
{
gtk_source_gutter_renderer_activate (renderer->renderer,
&line_iter,
&rect,
- (GdkEvent *)event);
+ button,
+ state,
+ n_presses);
do_redraw (gutter);
- return TRUE;
+ gtk_gesture_set_state (GTK_GESTURE (click),
+ GTK_EVENT_SEQUENCE_CLAIMED);
}
-
- return FALSE;
-}
-
-static gboolean
-on_view_query_tooltip (GtkSourceView *view,
- gint x,
- gint y,
- gboolean keyboard_mode,
- GtkTooltip *tooltip,
- GtkSourceGutter *gutter)
-{
- GtkTextView *text_view = GTK_TEXT_VIEW (view);
- Renderer *renderer;
- gint start = 0;
- gint width = 0;
- gint y_buf;
- gint yline;
- GtkTextIter line_iter;
- GdkRectangle rect;
-
- if (keyboard_mode)
- {
- return FALSE;
- }
-
- /* Check cell renderer */
- renderer = renderer_at_x (gutter, x, &start, &width);
-
- if (!renderer)
- {
- return FALSE;
- }
-
- gtk_text_view_window_to_buffer_coords (text_view,
- gutter->window_type,
- x, y,
- NULL, &y_buf);
-
- gtk_text_view_get_line_at_y (GTK_TEXT_VIEW (view),
- &line_iter,
- y_buf,
- &yline);
-
- if (yline > y_buf)
- {
- return FALSE;
- }
-
- 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);
}
static void
on_view_style_updated (GtkSourceView *view,
GtkSourceGutter *gutter)
{
- gtk_source_gutter_queue_draw (gutter);
+ do_redraw (gutter);
}
-/**
- * gtk_source_gutter_get_renderer_at_pos:
- * @gutter: A #GtkSourceGutter.
- * @x: The x position to get identified.
- * @y: The y position to get identified.
- *
- * Finds the #GtkSourceGutterRenderer at (x, y).
- *
- * Returns: (nullable) (transfer none): the renderer at (x, y) or %NULL.
- */
-/* TODO: better document this function. The (x,y) position is different from
- * the position passed to gtk_source_gutter_insert() and
- * gtk_source_gutter_reorder(). The (x,y) coordinate can come from a click
- * event, for example? Is the (x,y) a coordinate of the Gutter's GdkWindow?
- * Where is the (0,0)? And so on.
- * Also, this function doesn't seem to be used.
- */
-GtkSourceGutterRenderer *
-gtk_source_gutter_get_renderer_at_pos (GtkSourceGutter *gutter,
- gint x,
- gint y)
+GtkSourceGutterLines *
+_gtk_source_gutter_get_lines (GtkSourceGutter *gutter)
{
- Renderer *renderer;
-
g_return_val_if_fail (GTK_SOURCE_IS_GUTTER (gutter), NULL);
- renderer = renderer_at_x (gutter, x, NULL, NULL);
+ return gutter->lines;
+}
- if (renderer == NULL)
+void
+_gtk_source_gutter_queue_draw (GtkSourceGutter *gutter)
+{
+ for (const GList *iter = gutter->renderers; iter; iter = iter->next)
{
- return NULL;
- }
+ Renderer *renderer = iter->data;
- return renderer->renderer;
+ gtk_widget_queue_allocate (GTK_WIDGET (renderer->renderer));
+ }
}
diff --git a/gtksourceview/gtksourcegutter.h b/gtksourceview/gtksourcegutter.h
index 3fdf5b44..d25a1769 100644
--- a/gtksourceview/gtksourcegutter.h
+++ b/gtksourceview/gtksourcegutter.h
@@ -33,28 +33,17 @@ G_BEGIN_DECLS
#define GTK_SOURCE_TYPE_GUTTER (gtk_source_gutter_get_type())
GTK_SOURCE_AVAILABLE_IN_ALL
-G_DECLARE_FINAL_TYPE (GtkSourceGutter, gtk_source_gutter, GTK_SOURCE, GUTTER, GObject)
+G_DECLARE_FINAL_TYPE (GtkSourceGutter, gtk_source_gutter, GTK_SOURCE, GUTTER, GtkContainer)
GTK_SOURCE_AVAILABLE_IN_3_24
-GtkSourceView *gtk_source_gutter_get_view (GtkSourceGutter *gutter);
-GTK_SOURCE_AVAILABLE_IN_3_24
-GtkTextWindowType gtk_source_gutter_get_window_type (GtkSourceGutter *gutter);
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_gutter_insert (GtkSourceGutter *gutter,
- GtkSourceGutterRenderer *renderer,
- gint position);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_reorder (GtkSourceGutter *gutter,
- GtkSourceGutterRenderer *renderer,
- gint position);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_remove (GtkSourceGutter *gutter,
- GtkSourceGutterRenderer *renderer);
+GtkSourceView *gtk_source_gutter_get_view (GtkSourceGutter *gutter);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_queue_draw (GtkSourceGutter *gutter);
+gboolean gtk_source_gutter_insert (GtkSourceGutter *gutter,
+ GtkSourceGutterRenderer *renderer,
+ gint position);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceGutterRenderer *gtk_source_gutter_get_renderer_at_pos (GtkSourceGutter *gutter,
- gint x,
- gint y);
+void gtk_source_gutter_reorder (GtkSourceGutter *gutter,
+ GtkSourceGutterRenderer *renderer,
+ gint position);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutterrenderer-private.h b/gtksourceview/gtksourcegutterrenderer-private.h
index 790fa6df..44f085a6 100644
--- a/gtksourceview/gtksourcegutterrenderer-private.h
+++ b/gtksourceview/gtksourcegutterrenderer-private.h
@@ -21,13 +21,22 @@
#pragma once
#include <gtk/gtk.h>
+
#include "gtksourcetypes.h"
G_BEGIN_DECLS
G_GNUC_INTERNAL
-void _gtk_source_gutter_renderer_set_view (GtkSourceGutterRenderer *renderer,
- GtkTextView *view,
- GtkTextWindowType window_type);
+void _gtk_source_gutter_renderer_set_view (GtkSourceGutterRenderer *renderer,
+ GtkSourceView *view);
+G_GNUC_INTERNAL
+void _gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines);
+G_GNUC_INTERNAL
+void _gtk_source_gutter_renderer_snapshot (GtkSourceGutterRenderer *renderer,
+ GtkSnapshot *snapshot,
+ GtkSourceGutterLines *lines);
+G_GNUC_INTERNAL
+void _gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutterrenderer.c b/gtksourceview/gtksourcegutterrenderer.c
index bcc6e5dc..6cb113a0 100644
--- a/gtksourceview/gtksourcegutterrenderer.c
+++ b/gtksourceview/gtksourcegutterrenderer.c
@@ -20,8 +20,12 @@
#include "config.h"
+#include "gtksourcebuffer.h"
+#include "gtksourcegutter.h"
+#include "gtksourcegutter-private.h"
#include "gtksourcegutterrenderer.h"
#include "gtksourcegutterrenderer-private.h"
+#include "gtksourcegutterlines.h"
#include "gtksourcestylescheme.h"
#include "gtksourceview.h"
#include "gtksource-enumtypes.h"
@@ -39,9 +43,11 @@
* this case, #GtkSourceGutterRendererAlignmentMode controls the alignment of
* the cell.
*
- * The gutter renderer must announce its #GtkSourceGutterRenderer:size. The
- * height is determined by the text view height. The width must be determined by
- * the gutter renderer. The width generally takes into account the entire text
+ * The gutter renderer is a #GtkWidget and is measured using the normal widget
+ * measurement facilities. The width of the gutter will be determined by the
+ * measurements of the gutter renderers.
+ *
+ * The width of a gutter renderer generally takes into account the entire text
* buffer. For instance, to display the line numbers, if the buffer contains 100
* lines, the gutter renderer will always set its width such as three digits can
* be printed, even if only the first 20 lines are shown. Another strategy is to
@@ -51,122 +57,84 @@
* into account the text buffer to announce its width. It only depends on the
* icons size displayed in the gutter column.
*
- * An horizontal and vertical padding can be added with
- * gtk_source_gutter_renderer_set_padding(). The total width of a gutter
- * renderer is its size (#GtkSourceGutterRenderer:size) plus two times the
- * horizontal padding (#GtkSourceGutterRenderer:xpad).
- *
* When the available size to render a cell is greater than the required size to
* render the cell contents, the cell contents can be aligned horizontally and
* vertically with gtk_source_gutter_renderer_set_alignment().
*
- * The cells rendering occurs in three phases:
- * - begin: the gtk_source_gutter_renderer_begin() function is called when some
- * cells need to be redrawn. It provides the associated region of the
- * #GtkTextBuffer. The cells need to be redrawn when the #GtkTextView is
- * scrolled, or when the state of the cells change (see
- * #GtkSourceGutterRendererState).
- * - draw: gtk_source_gutter_renderer_draw() is called for each cell that needs
- * to be drawn.
- * - end: finally, gtk_source_gutter_renderer_end() is called.
+ * The cells rendering occurs using gtk_widget_snapshot(). Implementations
+ * should use gtk_source_gutter_renderer_get_lines() to retrieve information
+ * about the lines to be rendered. To help with aligning content which takes
+ * into account the padding and alignment of a cell, implementations may call
+ * gtk_source_gutter_renderer_align_cell() for a given line number with the
+ * width and height measurement of the content they width to render.
*/
-enum
-{
- ACTIVATE,
- QUEUE_DRAW,
- QUERY_TOOLTIP,
- QUERY_DATA,
- QUERY_ACTIVATABLE,
- N_SIGNALS
-};
-
typedef struct
{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkTextWindowType window_type;
-
- gint xpad;
- gint ypad;
+ GtkSourceGutter *gutter;
+ GtkSourceView *view;
+ GtkSourceBuffer *buffer;
+ GtkSourceGutterLines *lines;
gfloat xalign;
gfloat yalign;
- gint size;
+ gint xpad;
+ gint ypad;
GtkSourceGutterRendererAlignmentMode alignment_mode;
- GdkRGBA background_color;
-
- guint background_set : 1;
guint visible : 1;
} GtkSourceGutterRendererPrivate;
-static guint signals[N_SIGNALS];
-
-G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkSourceGutterRenderer, gtk_source_gutter_renderer,
G_TYPE_INITIALLY_UNOWNED)
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkSourceGutterRenderer, gtk_source_gutter_renderer, GTK_TYPE_WIDGET)
enum
{
PROP_0,
- PROP_VISIBLE,
- PROP_XPAD,
- PROP_YPAD,
+ PROP_ALIGNMENT_MODE,
+ PROP_LINES,
+ PROP_VIEW,
PROP_XALIGN,
+ PROP_XPAD,
PROP_YALIGN,
- PROP_VIEW,
- PROP_ALIGNMENT_MODE,
- PROP_WINDOW_TYPE,
- PROP_SIZE,
- PROP_BACKGROUND_RGBA,
- PROP_BACKGROUND_SET
+ PROP_YPAD,
+ N_PROPS
};
-static void
-set_buffer (GtkSourceGutterRenderer *renderer,
- GtkTextBuffer *buffer)
+enum
{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- if (priv->buffer != NULL)
- {
- g_object_remove_weak_pointer (G_OBJECT (priv->buffer),
- (gpointer) &priv->buffer);
- }
-
- if (buffer != NULL)
- {
- g_object_add_weak_pointer (G_OBJECT (buffer),
- (gpointer) &priv->buffer);
- }
+ ACTIVATE,
+ QUERY_ACTIVATABLE,
+ QUERY_DATA,
+ N_SIGNALS
+};
- priv->buffer = buffer;
-}
+static GParamSpec *properties[N_PROPS];
+static guint signals[N_SIGNALS];
static void
-emit_buffer_changed (GtkTextView *view,
+emit_buffer_changed (GtkSourceView *view,
GtkSourceGutterRenderer *renderer)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- GtkTextBuffer* buffer;
+ GtkSourceBuffer *buffer;
+ GtkSourceBuffer *old_buffer;
- buffer = gtk_text_view_get_buffer (view);
+ old_buffer = priv->buffer;
+ buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- if (buffer != priv->buffer)
+ if (buffer == old_buffer)
{
- if (GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_buffer)
- {
- GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_buffer (renderer,
- priv->buffer);
- }
-
- set_buffer (renderer, buffer);
+ return;
}
+
+ g_set_weak_pointer (&priv->buffer, buffer);
+ GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_buffer (renderer, old_buffer);
}
static void
-on_buffer_changed (GtkTextView *view,
+on_buffer_changed (GtkSourceView *view,
GParamSpec *spec,
GtkSourceGutterRenderer *renderer)
{
@@ -174,19 +142,25 @@ on_buffer_changed (GtkTextView *view,
}
static void
-renderer_change_view_impl (GtkSourceGutterRenderer *renderer,
- GtkTextView *old_view)
+gtk_source_gutter_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
+ GtkSourceBuffer *buffer)
+{
+}
+
+static void
+gtk_source_gutter_renderer_change_view (GtkSourceGutterRenderer *renderer,
+ GtkSourceView *old_view)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- if (old_view)
+ if (old_view != NULL)
{
g_signal_handlers_disconnect_by_func (old_view,
G_CALLBACK (on_buffer_changed),
renderer);
}
- if (priv->view)
+ if (priv->view != NULL)
{
emit_buffer_changed (priv->view, renderer);
@@ -198,196 +172,98 @@ renderer_change_view_impl (GtkSourceGutterRenderer *renderer,
}
static void
-gtk_source_gutter_renderer_dispose (GObject *object)
+gtk_source_gutter_renderer_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
- GtkSourceGutterRenderer *renderer = GTK_SOURCE_GUTTER_RENDERER (object);
+ GtkSourceGutterRenderer *renderer = GTK_SOURCE_GUTTER_RENDERER (widget);
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ GtkSourceGutterRendererClass *klass = GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (widget);
+ GtkSourceGutterRendererAlignmentMode mode = priv->alignment_mode;
+ GtkSourceGutterLines *lines = priv->lines;
+ guint first;
+ guint last;
+ guint line;
+ gint y;
+ gint h;
- set_buffer (renderer, NULL);
-
- if (priv->view)
+ if (lines == NULL || klass->snapshot_line == NULL)
{
- _gtk_source_gutter_renderer_set_view (renderer,
- NULL,
- GTK_TEXT_WINDOW_PRIVATE);
+ return;
}
- G_OBJECT_CLASS (gtk_source_gutter_renderer_parent_class)->dispose (object);
-}
+ first = gtk_source_gutter_lines_get_first (lines);
+ last = gtk_source_gutter_lines_get_last (lines);
-static void
-set_visible (GtkSourceGutterRenderer *renderer,
- gboolean visible)
-{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- visible = visible != FALSE;
-
- if (priv->visible != visible)
+ for (line = first; line <= last; line++)
{
- priv->visible = visible;
- g_object_notify (G_OBJECT (renderer), "visible");
+ gtk_source_gutter_lines_get_line_yrange (lines, line, mode, &y, &h);
- gtk_source_gutter_renderer_queue_draw (renderer);
+ klass->query_data (renderer, lines, line);
+ klass->snapshot_line (renderer, snapshot, lines, line);
}
}
-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)
-{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- return set_padding (renderer,
- &priv->xpad,
- xpad,
- "xpad");
-}
-
-static gboolean
-set_ypad (GtkSourceGutterRenderer *renderer,
- gint ypad)
+static void
+gtk_source_gutter_renderer_dispose (GObject *object)
{
+ GtkSourceGutterRenderer *renderer = GTK_SOURCE_GUTTER_RENDERER (object);
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- return set_padding (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);
+ g_clear_weak_pointer (&priv->buffer);
- if (emit)
+ if (priv->view != NULL)
{
- gtk_source_gutter_renderer_queue_draw (renderer);
+ _gtk_source_gutter_renderer_set_view (renderer, NULL);
}
- return TRUE;
+ G_OBJECT_CLASS (gtk_source_gutter_renderer_parent_class)->dispose (object);
}
-static gboolean
-set_xalign (GtkSourceGutterRenderer *renderer,
- gfloat xalign,
- gboolean emit)
+static void
+gtk_source_gutter_renderer_root (GtkWidget *widget)
{
+ GtkSourceGutterRenderer *renderer = GTK_SOURCE_GUTTER_RENDERER (widget);
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ GtkWidget *gutter;
- return set_alignment (renderer,
- &priv->xalign,
- xalign,
- "xalign",
- emit);
-}
+ GTK_WIDGET_CLASS (gtk_source_gutter_renderer_parent_class)->root (widget);
-static gboolean
-set_yalign (GtkSourceGutterRenderer *renderer,
- gfloat yalign,
- gboolean emit)
-{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ gutter = gtk_widget_get_ancestor (widget, GTK_SOURCE_TYPE_GUTTER);
- return set_alignment (renderer,
- &priv->yalign,
- yalign,
- "yalign",
- emit);
+ if (GTK_SOURCE_IS_GUTTER (gutter))
+ {
+ priv->gutter = GTK_SOURCE_GUTTER (gutter);
+ }
}
static void
-set_alignment_mode (GtkSourceGutterRenderer *renderer,
- GtkSourceGutterRendererAlignmentMode mode)
+gtk_source_gutter_renderer_unroot (GtkWidget *widget)
{
+ GtkSourceGutterRenderer *renderer = GTK_SOURCE_GUTTER_RENDERER (widget);
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- if (priv->alignment_mode == mode)
- {
- return;
- }
-
- priv->alignment_mode = mode;
- g_object_notify (G_OBJECT (renderer), "alignment-mode");
+ priv->gutter = NULL;
- gtk_source_gutter_renderer_queue_draw (renderer);
+ GTK_WIDGET_CLASS (gtk_source_gutter_renderer_parent_class)->unroot (widget);
}
static void
-set_size (GtkSourceGutterRenderer *renderer,
- gint value)
+gtk_source_gutter_renderer_real_begin (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines)
{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- if (priv->size == value)
- {
- return;
- }
-
- priv->size = value;
- g_object_notify (G_OBJECT (renderer), "size");
}
static void
-set_background_color_set (GtkSourceGutterRenderer *renderer,
- gboolean isset)
+gtk_source_gutter_renderer_real_end (GtkSourceGutterRenderer *renderer)
{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- isset = (isset != FALSE);
-
- if (isset != priv->background_set)
- {
- priv->background_set = isset;
- gtk_source_gutter_renderer_queue_draw (renderer);
- }
}
static void
-set_background_color (GtkSourceGutterRenderer *renderer,
- const GdkRGBA *color)
+gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines,
+ guint line)
{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- if (!color)
- {
- set_background_color_set (renderer, FALSE);
- }
- else
- {
- priv->background_color = *color;
- priv->background_set = TRUE;
-
- gtk_source_gutter_renderer_queue_draw (renderer);
- }
+ g_signal_emit (renderer, signals[QUERY_DATA], 0, lines, line);
}
static void
@@ -397,45 +273,29 @@ gtk_source_gutter_renderer_set_property (GObject *object,
GParamSpec *pspec)
{
GtkSourceGutterRenderer *self = GTK_SOURCE_GUTTER_RENDERER (object);
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (self);
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));
+ gtk_source_gutter_renderer_set_xpad (self, g_value_get_int (value));
break;
+
case PROP_YPAD:
- set_ypad (self, g_value_get_int (value));
+ gtk_source_gutter_renderer_set_ypad (self, g_value_get_int (value));
break;
+
case PROP_XALIGN:
- set_xalign (self, g_value_get_float (value), TRUE);
+ gtk_source_gutter_renderer_set_xalign (self, g_value_get_float (value));
break;
+
case PROP_YALIGN:
- set_yalign (self, g_value_get_float (value), TRUE);
+ gtk_source_gutter_renderer_set_yalign (self, g_value_get_float (value));
break;
+
case PROP_ALIGNMENT_MODE:
- set_alignment_mode (self, g_value_get_enum (value));
- break;
- case PROP_VIEW:
- priv->view = g_value_get_object (value);
- break;
- case PROP_WINDOW_TYPE:
- priv->window_type = g_value_get_enum (value);
- break;
- case PROP_SIZE:
- set_size (self, g_value_get_int (value));
- break;
- case PROP_BACKGROUND_RGBA:
- set_background_color (self,
- g_value_get_boxed (value));
- break;
- case PROP_BACKGROUND_SET:
- set_background_color_set (self,
- g_value_get_boolean (value));
+ gtk_source_gutter_renderer_set_alignment_mode (self, g_value_get_enum (value));
break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -453,142 +313,101 @@ gtk_source_gutter_renderer_get_property (GObject *object,
switch (prop_id)
{
- case PROP_VISIBLE:
- g_value_set_boolean (value, priv->visible);
- break;
- case PROP_XPAD:
- g_value_set_int (value, priv->xpad);
- break;
- case PROP_YPAD:
- g_value_set_int (value, priv->ypad);
+ case PROP_LINES:
+ g_value_set_object (value, priv->lines);
break;
+
case PROP_XALIGN:
g_value_set_float (value, priv->xalign);
break;
+
+ case PROP_XPAD:
+ g_value_set_int (value, priv->xpad);
+ break;
+
case PROP_YALIGN:
g_value_set_float (value, priv->yalign);
break;
+
+ case PROP_YPAD:
+ g_value_set_int (value, priv->ypad);
+ break;
+
case PROP_VIEW:
g_value_set_object (value, priv->view);
break;
+
case PROP_ALIGNMENT_MODE:
g_value_set_enum (value, priv->alignment_mode);
break;
- case PROP_WINDOW_TYPE:
- g_value_set_enum (value, priv->window_type);
- break;
- case PROP_SIZE:
- g_value_set_int (value, priv->size);
- break;
- case PROP_BACKGROUND_RGBA:
- g_value_set_boxed (value, &priv->background_color);
- break;
- case PROP_BACKGROUND_SET:
- g_value_set_boolean (value, 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,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
-{
- GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
-
- if (priv->background_set)
- {
- cairo_save (cr);
- gdk_cairo_rectangle (cr, background_area);
- gdk_cairo_set_source_rgba (cr, &priv->background_color);
- cairo_fill (cr);
- cairo_restore (cr);
- }
- else if ((state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR) != 0 &&
- GTK_SOURCE_IS_VIEW (priv->view) &&
- gtk_source_view_get_highlight_current_line (GTK_SOURCE_VIEW (priv->view)))
- {
- GtkStyleContext *context;
-
- context = gtk_widget_get_style_context (GTK_WIDGET (priv->view));
-
- gtk_style_context_save (context);
- gtk_style_context_add_class (context, "current-line-number");
-
- gtk_render_background (context,
- cr,
- background_area->x,
- background_area->y,
- background_area->width,
- background_area->height);
-
- gtk_style_context_restore (context);
- }
-}
-
static void
gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = gtk_source_gutter_renderer_dispose;
-
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;
- klass->change_view = renderer_change_view_impl;
+ widget_class->root = gtk_source_gutter_renderer_root;
+ widget_class->unroot = gtk_source_gutter_renderer_unroot;
+ widget_class->snapshot = gtk_source_gutter_renderer_snapshot;
+
+ klass->begin = gtk_source_gutter_renderer_real_begin;
+ klass->end = gtk_source_gutter_renderer_real_end;
+ klass->change_buffer = gtk_source_gutter_renderer_change_buffer;
+ klass->change_view = gtk_source_gutter_renderer_change_view;
+ klass->query_data = gtk_source_gutter_renderer_query_data;
/**
- * GtkSourceGutterRenderer:visible:
+ * GtkSourceGutterRenderer:lines:
*
- * 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));
+ * The "lines" property contains information about the lines to be
+ * rendered. It should be used by #GtkSourceGutterRenderer
+ * implementations from gtk_widget_snapshot().
+ */
+ properties[PROP_LINES] =
+ g_param_spec_object ("lines",
+ "Lines",
+ "Information about the lines to render",
+ GTK_SOURCE_TYPE_GUTTER_LINES,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GtkSourceGutterRenderer:xpad:
*
* The left and right 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));
+ properties[PROP_XPAD] =
+ g_param_spec_int ("xpad",
+ "X Padding",
+ "The x-padding",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* GtkSourceGutterRenderer:ypad:
*
* The top and bottom 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));
+ properties[PROP_YPAD] =
+ g_param_spec_int ("ypad",
+ "Y Padding",
+ "The y-padding",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* GtkSourceGutterRenderer:xalign:
@@ -597,15 +416,14 @@ gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
* alignment. 1 for a right alignment. And 0.5 for centering the cells.
* A value lower than 0 doesn't modify the alignment.
*/
- 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));
+ properties[PROP_XALIGN] =
+ g_param_spec_float ("xalign",
+ "X Alignment",
+ "The x-alignment",
+ 0.0,
+ 1.0,
+ 0.0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* GtkSourceGutterRenderer:yalign:
@@ -614,124 +432,75 @@ gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
* alignment. 1 for a bottom alignment. And 0.5 for centering the cells.
* A value lower than 0 doesn't modify the alignment.
*/
- 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));
+ properties[PROP_YALIGN] =
+ g_param_spec_float ("yalign",
+ "Y Alignment",
+ "The y-alignment",
+ 0.0,
+ 1.0,
+ 0.0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- /**
- * 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,
- _gtk_source_marshal_VOID__BOXED_BOXED_BOXED,
- G_TYPE_NONE,
- 3,
- GTK_TYPE_TEXT_ITER,
- GDK_TYPE_RECTANGLE,
- GDK_TYPE_EVENT);
- g_signal_set_va_marshaller (signals[ACTIVATE],
- G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_VOID__BOXED_BOXED_BOXEDv);
/**
- * GtkSourceGutterRenderer::queue-draw:
- * @renderer: the #GtkSourceGutterRenderer who emits the signal
+ * GtkSourceGutterRenderer:view:
*
- * 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);
- g_signal_set_va_marshaller (signals[QUEUE_DRAW],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
+ * The view on which the renderer is placed.
+ **/
+ properties[PROP_VIEW] =
+ g_param_spec_object ("view",
+ "The View",
+ "The view",
+ GTK_TYPE_TEXT_VIEW,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
- * 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
+ * GtkSourceGutterRenderer:alignment-mode:
*
- * The ::query-tooltip signal is emitted when the renderer can
- * show a tooltip.
+ * 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.
*
- */
- 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,
- _gtk_source_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);
- g_signal_set_va_marshaller (signals[QUERY_TOOLTIP],
- G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_BOOLEAN__BOXED_BOXED_INT_INT_OBJECTv);
+ **/
+ properties[PROP_ALIGNMENT_MODE] =
+ g_param_spec_enum ("alignment-mode",
+ "Alignment Mode",
+ "The alignment mode",
+ GTK_SOURCE_TYPE_GUTTER_RENDERER_ALIGNMENT_MODE,
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
/**
- * GtkSourceGutterRenderer::query-data:
+ * GtkSourceGutterRenderer::activate:
* @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.
+ * @iter: a #GtkTextIter
+ * @area: a #GdkRectangle
+ * @button: the button that was pressed
+ * @state: a #GdkModifierType of state
+ * @n_presses: the number of button presses
*
+ * The ::activate signal is emitted when the renderer is activated.
*/
- signals[QUERY_DATA] =
- g_signal_new ("query-data",
- G_TYPE_FROM_CLASS (object_class),
+ signals[ACTIVATE] =
+ g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_data),
+ G_STRUCT_OFFSET (GtkSourceGutterRendererClass, activate),
NULL, NULL,
- _gtk_source_marshal_VOID__BOXED_BOXED_FLAGS,
+ _gtk_source_marshal_VOID__BOXED_BOXED_UINT_FLAGS_INT,
G_TYPE_NONE,
- 3,
- GTK_TYPE_TEXT_ITER,
- GTK_TYPE_TEXT_ITER,
- GTK_SOURCE_TYPE_GUTTER_RENDERER_STATE);
- g_signal_set_va_marshaller (signals[QUERY_DATA],
+ 5,
+ GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
+ GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE,
+ G_TYPE_UINT,
+ GDK_TYPE_MODIFIER_TYPE,
+ G_TYPE_INT);
+ g_signal_set_va_marshaller (signals[ACTIVATE],
G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_VOID__BOXED_BOXED_FLAGSv);
+ _gtk_source_marshal_VOID__BOXED_BOXED_UINT_FLAGS_INTv);
/**
* GtkSourceGutterRenderer::query-activatable:
@@ -742,98 +511,39 @@ gtk_source_gutter_renderer_class_init (GtkSourceGutterRendererClass *klass)
*
* 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_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkSourceGutterRendererClass, query_activatable),
g_signal_accumulator_true_handled,
NULL,
- _gtk_source_marshal_BOOLEAN__BOXED_BOXED_BOXED,
+ _gtk_source_marshal_BOOLEAN__BOXED_BOXED,
G_TYPE_BOOLEAN,
- 3,
- GTK_TYPE_TEXT_ITER,
- GDK_TYPE_RECTANGLE,
- GDK_TYPE_EVENT);
+ 2,
+ GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE,
+ GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
g_signal_set_va_marshaller (signals[QUERY_ACTIVATABLE],
G_TYPE_FROM_CLASS (klass),
- _gtk_source_marshal_BOOLEAN__BOXED_BOXED_BOXEDv);
+ _gtk_source_marshal_BOOLEAN__BOXED_BOXEDv);
- /**
- * 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_READABLE));
-
- /**
- * 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_SOURCE_TYPE_GUTTER_RENDERER_ALIGNMENT_MODE,
- GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ signals[QUERY_DATA] =
+ g_signal_new ("query-data",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ _gtk_source_marshal_VOID__OBJECT_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_OBJECT,
+ G_TYPE_UINT);
+ g_signal_set_va_marshaller (signals[QUERY_DATA],
+ G_TYPE_FROM_CLASS (klass),
+ _gtk_source_marshal_VOID__OBJECT_UINTv);
- /**
- * 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_READABLE));
-
- 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_RGBA,
- g_param_spec_boxed ("background-rgba",
- "Background Color",
- "The background color",
- GDK_TYPE_RGBA,
- 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));
+ gtk_widget_class_set_css_name (widget_class, "gutterrenderer");
}
static void
@@ -841,125 +551,13 @@ gtk_source_gutter_renderer_init (GtkSourceGutterRenderer *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,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end)
-{
- g_return_if_fail (GTK_SOURCE_IS_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 the total area of the
- * cell to be drawn. The @cell_area indicates the area where content can be
- * drawn (text, images, etc).
- *
- * The @background_area is the @cell_area plus the padding on each side (two
- * times the #GtkSourceGutterRenderer:xpad horizontally and two times the
- * #GtkSourceGutterRenderer:ypad vertically, so that the @cell_area is centered
- * inside @background_area).
- *
- * 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,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
-{
- g_return_if_fail (GTK_SOURCE_IS_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_SOURCE_IS_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
+ * Get whether the renderer is activatable at the location provided. This is
* called from #GtkSourceGutter to determine whether a renderer is activatable
* using the mouse pointer.
*
@@ -968,16 +566,14 @@ gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
**/
gboolean
gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
- GtkTextIter *iter,
- GdkRectangle *area,
- GdkEvent *event)
+ const GtkTextIter *iter,
+ const GdkRectangle *area)
{
gboolean ret;
g_return_val_if_fail (GTK_SOURCE_IS_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;
@@ -986,7 +582,6 @@ gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
0,
iter,
area,
- event,
&ret);
return ret;
@@ -997,463 +592,427 @@ gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
* @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
+ * @button: the button that was pressed
+ * @state: a #GdkModifierType
+ * @n_presses: the number of button presses
*
* Emits the #GtkSourceGutterRenderer::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,
- GdkRectangle *area,
- GdkEvent *event)
+ const GtkTextIter *iter,
+ const GdkRectangle *area,
+ guint button,
+ GdkModifierType state,
+ gint n_presses)
{
g_return_if_fail (GTK_SOURCE_IS_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);
+ g_signal_emit (renderer, signals[ACTIVATE], 0, iter, area, button, state, n_presses);
}
/**
- * gtk_source_gutter_renderer_queue_draw:
+ * gtk_source_gutter_renderer_set_alignment_mode:
* @renderer: a #GtkSourceGutterRenderer
+ * @mode: a #GtkSourceGutterRendererAlignmentMode
*
- * Emits the #GtkSourceGutterRenderer::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_SOURCE_IS_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 #GtkSourceGutterRenderer::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,
- GdkRectangle *area,
- gint x,
- gint y,
- GtkTooltip *tooltip)
-{
- gboolean ret;
-
- g_return_val_if_fail (GTK_SOURCE_IS_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 #GtkSourceGutterRenderer::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
- * #GtkSourceGutterRenderer::query-data signal.
- */
+ * Set the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see #GtkSourceGutterRenderer:xalign and
+ * #GtkSourceGutterRenderer:yalign).
+ **/
void
-gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
+gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterRendererAlignmentMode mode)
{
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
- g_return_if_fail (start != NULL);
- g_return_if_fail (end != NULL);
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ g_return_if_fail (GTK_SOURCE_GUTTER_RENDERER (renderer));
+ g_return_if_fail (mode == GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL ||
+ mode == GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST ||
+ mode == GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST);
- /* Signal emission is relatively expensive and this code path is
- * frequent enough to optimize the common case where we only have the
- * override and no connected handlers.
- *
- * This is the same trick used by gtk_widget_draw().
- */
- if (G_UNLIKELY (g_signal_has_handler_pending (renderer, signals[QUERY_DATA], 0, FALSE)))
- {
- g_signal_emit (renderer, signals[QUERY_DATA], 0, start, end, state);
- }
- else if (GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->query_data)
+ if (priv->alignment_mode != mode)
{
- GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->query_data (renderer, start, end, state);
+ priv->alignment_mode = mode;
+ g_object_notify_by_pspec (G_OBJECT (renderer),
+ properties[PROP_ALIGNMENT_MODE]);
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
}
}
/**
- * gtk_source_gutter_renderer_set_visible:
+ * gtk_source_gutter_renderer_get_alignment_mode:
* @renderer: a #GtkSourceGutterRenderer
- * @visible: the visibility
*
- * Set whether the gutter renderer is visible.
+ * Get the alignment mode. The alignment mode describes the manner in which the
+ * renderer is aligned (see :xalign and :yalign).
*
+ * Returns: a #GtkSourceGutterRendererAlignmentMode
**/
-void
-gtk_source_gutter_renderer_set_visible (GtkSourceGutterRenderer *renderer,
- gboolean visible)
+GtkSourceGutterRendererAlignmentMode
+gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer *renderer)
{
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- set_visible (renderer, visible);
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
+
+ return priv->alignment_mode;
}
/**
- * gtk_source_gutter_renderer_get_visible:
+ * gtk_source_gutter_renderer_get_view:
* @renderer: a #GtkSourceGutterRenderer
*
- * Get whether the gutter renderer is visible.
- *
- * Returns: %TRUE if the renderer is visible, %FALSE otherwise
+ * Get the view associated to the gutter renderer
*
+ * Returns: (transfer none): a #GtkSourceView
**/
-gboolean
-gtk_source_gutter_renderer_get_visible (GtkSourceGutterRenderer *renderer)
+GtkSourceView *
+gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer *renderer)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), FALSE);
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), NULL);
- return priv->visible;
+ return GTK_SOURCE_VIEW (priv->view);
}
-/**
- * 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).
- *
- * @xpad is the left and right padding. @ypad is the top and bottom padding.
- */
void
-gtk_source_gutter_renderer_set_padding (GtkSourceGutterRenderer *renderer,
- gint xpad,
- gint ypad)
+_gtk_source_gutter_renderer_set_view (GtkSourceGutterRenderer *renderer,
+ GtkSourceView *view)
{
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ GtkSourceView *old_view;
+
g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ g_return_if_fail (view == NULL || GTK_SOURCE_IS_VIEW (view));
+
+ if (view == priv->view)
+ {
+ return;
+ }
+
+ old_view = g_steal_pointer (&priv->view);
+ g_set_object (&priv->view, view);
+
+ GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_view (renderer, old_view);
+
+ g_clear_object (&old_view);
- set_xpad (renderer, xpad);
- set_ypad (renderer, ypad);
+ g_object_notify_by_pspec (G_OBJECT (renderer), properties[PROP_VIEW]);
}
-/**
- * gtk_source_gutter_renderer_get_padding:
- * @renderer: a #GtkSourceGutterRenderer
- * @xpad: (out caller-allocates) (optional): return location for the x-padding,
- * or %NULL to ignore.
- * @ypad: (out caller-allocates) (optional): return location for the y-padding,
- * or %NULL to ignore.
- *
- * Get the x-padding and y-padding of the gutter renderer.
- */
-void
-gtk_source_gutter_renderer_get_padding (GtkSourceGutterRenderer *renderer,
- gint *xpad,
- gint *ypad)
+static void
+get_line_rect (GtkSourceGutterRenderer *renderer,
+ guint line,
+ GdkRectangle *rect)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ GtkSourceGutterLines *lines = NULL;
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
-
- if (xpad)
+ if (priv->gutter != NULL)
{
- *xpad = priv->xpad;
+ lines = _gtk_source_gutter_get_lines (priv->gutter);
}
- if (ypad)
+ if (lines != NULL)
+ {
+ gint y;
+ gint height;
+
+ gtk_source_gutter_lines_get_line_yrange (lines,
+ line,
+ priv->alignment_mode,
+ &y,
+ &height);
+
+ rect->x = priv->xpad;
+ rect->y = y + priv->ypad;
+ rect->width = gtk_widget_get_width (GTK_WIDGET (renderer));
+ rect->height = height;
+
+ rect->width -= 2 * priv->xpad;
+ rect->height -= 2 * priv->ypad;
+ }
+ else
{
- *ypad = priv->ypad;
+ rect->x = 0;
+ rect->y = 0;
+ rect->width = 0;
+ rect->height = 0;
}
}
/**
- * gtk_source_gutter_renderer_set_alignment:
- * @renderer: a #GtkSourceGutterRenderer
- * @xalign: the x-alignment
- * @yalign: the y-alignment
+ * gtk_source_gutter_renderer_align_cell:
+ * @renderer: the #GtkSourceGutterRenderer
+ * @line: the line number for content
+ * @width: the width of the content to draw
+ * @height: the height of the content to draw
+ * @x: (out): the X position to render the content
+ * @y: (out): the Y position to render the content
*
- * 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).
+ * Locates where to render content that is @width x @height based on
+ * the renderers alignment and padding.
*
- * @xalign is the horizontal alignment. Set to 0 for a left alignment. 1 for a
- * right alignment. And 0.5 for centering the cells. @yalign is the vertical
- * alignment. Set to 0 for a top alignment. 1 for a bottom alignment.
+ * The location will be placed into @x and @y and is relative to the
+ * renderer's coordinates.
+ *
+ * It is encouraged that renderers use this function when snappshotting
+ * to ensure consistent placement of their contents.
+ *
+ * Since: 5.0
*/
void
-gtk_source_gutter_renderer_set_alignment (GtkSourceGutterRenderer *renderer,
- gfloat xalign,
- gfloat yalign)
+gtk_source_gutter_renderer_align_cell (GtkSourceGutterRenderer *renderer,
+ guint line,
+ gfloat width,
+ gfloat height,
+ gfloat *x,
+ gfloat *y)
{
- gboolean changed_x;
- gboolean changed_y;
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+ GdkRectangle rect;
g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
- changed_x = set_xalign (renderer, xalign, FALSE);
- changed_y = set_yalign (renderer, yalign, FALSE);
+ get_line_rect (renderer, line, &rect);
- if (changed_x || changed_y)
- {
- gtk_source_gutter_renderer_queue_draw (renderer);
- }
+ *x = rect.x + (rect.width - width) * priv->xalign;
+ *y = rect.y + (rect.height - height) * priv->yalign;
}
/**
- * gtk_source_gutter_renderer_get_alignment:
+ * gtk_source_gutter_renderer_get_xpad:
* @renderer: a #GtkSourceGutterRenderer
- * @xalign: (out caller-allocates) (optional): return location for the x-alignment,
- * or %NULL to ignore.
- * @yalign: (out caller-allocates) (optional): return location for the y-alignment,
- * or %NULL to ignore.
*
- * Get the x-alignment and y-alignment of the gutter renderer.
+ * Gets the "xpad" property of the #GtkSourceGutterRenderer. This may be used
+ * to adjust the cell rectangle that the renderer will use to draw.
+ *
+ * Since: 5.0
*/
-void
-gtk_source_gutter_renderer_get_alignment (GtkSourceGutterRenderer *renderer,
- gfloat *xalign,
- gfloat *yalign)
+gint
+gtk_source_gutter_renderer_get_xpad (GtkSourceGutterRenderer *renderer)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
-
- if (xalign)
- {
- *xalign = priv->xalign;
- }
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
- if (yalign)
- {
- *yalign = priv->yalign;
- }
+ return priv->xpad;
}
/**
- * gtk_source_gutter_renderer_set_alignment_mode:
+ * gtk_source_gutter_renderer_set_xpad:
* @renderer: a #GtkSourceGutterRenderer
- * @mode: a #GtkSourceGutterRendererAlignmentMode
+ * @xpad: the Y padding for the drawing cell
*
- * Set the alignment mode. The alignment mode describes the manner in which the
- * renderer is aligned (see :xalign and :yalign).
+ * Adjusts the "xpad" property of the #GtkSourceGutterRenderer. This may be
+ * used to adjust the cell rectangle that the renderer will use to draw.
*
- **/
+ * Since: 5.0
+ */
void
-gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer *renderer,
- GtkSourceGutterRendererAlignmentMode mode)
+gtk_source_gutter_renderer_set_xpad (GtkSourceGutterRenderer *renderer,
+ gint xpad)
{
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+
g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ g_return_if_fail (xpad >= 0);
- set_alignment_mode (renderer, mode);
+ if (priv->xpad != xpad)
+ {
+ priv->xpad = xpad;
+ g_object_notify_by_pspec (G_OBJECT (renderer),
+ properties[PROP_XPAD]);
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
+ }
}
/**
- * gtk_source_gutter_renderer_get_alignment_mode:
+ * gtk_source_gutter_renderer_get_ypad:
* @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
+ * Gets the "ypad" property of the #GtkSourceGutterRenderer. This may be used
+ * to adjust the cell rectangle that the renderer will use to draw.
*
- **/
-GtkSourceGutterRendererAlignmentMode
-gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer *renderer)
+ * Since: 5.0
+ */
+gint
+gtk_source_gutter_renderer_get_ypad (GtkSourceGutterRenderer *renderer)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
- return priv->alignment_mode;
+ return priv->ypad;
}
/**
- * gtk_source_gutter_renderer_get_window_type:
+ * gtk_source_gutter_renderer_set_ypad:
* @renderer: a #GtkSourceGutterRenderer
+ * @ypad: the Y padding for the drawing cell
*
- * Get the #GtkTextWindowType associated with the gutter renderer.
+ * Adjusts the "ypad" property of the #GtkSourceGutterRenderer. This may be
+ * used to adjust the cell rectangle that the renderer will use to draw.
*
- * Returns: a #GtkTextWindowType
- *
- **/
-GtkTextWindowType
-gtk_source_gutter_renderer_get_window_type (GtkSourceGutterRenderer *renderer)
+ * Since: 5.0
+ */
+void
+gtk_source_gutter_renderer_set_ypad (GtkSourceGutterRenderer *renderer,
+ gint ypad)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), GTK_TEXT_WINDOW_PRIVATE);
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ g_return_if_fail (ypad >= 0);
- return priv->window_type;
+ if (priv->ypad != ypad)
+ {
+ priv->ypad = ypad;
+ g_object_notify_by_pspec (G_OBJECT (renderer),
+ properties[PROP_YPAD]);
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
+ }
}
/**
- * gtk_source_gutter_renderer_get_view:
+ * gtk_source_gutter_renderer_get_xalign:
* @renderer: a #GtkSourceGutterRenderer
*
- * Get the view associated to the gutter renderer
- *
- * Returns: (transfer none): a #GtkTextView
+ * Gets the "xalign" property of the #GtkSourceGutterRenderer. This may be used
+ * to adjust where within the cell rectangle the renderer will draw.
*
- **/
-GtkTextView *
-gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer *renderer)
+ * Since: 5.0
+ */
+gfloat
+gtk_source_gutter_renderer_get_xalign (GtkSourceGutterRenderer *renderer)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), NULL);
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
- return priv->view;
+ return priv->xalign;
}
/**
- * gtk_source_gutter_renderer_get_size:
+ * gtk_source_gutter_renderer_set_xalign:
* @renderer: a #GtkSourceGutterRenderer
+ * @xalign: the Y padding for the drawing cell
*
- * Get the size of the renderer.
+ * Adjusts the "xalign" property of the #GtkSourceGutterRenderer. This may be
+ * used to adjust where within the cell rectangle the renderer will draw.
*
- * Returns: the size of the renderer.
- *
- **/
-gint
-gtk_source_gutter_renderer_get_size (GtkSourceGutterRenderer *renderer)
+ * Since: 5.0
+ */
+void
+gtk_source_gutter_renderer_set_xalign (GtkSourceGutterRenderer *renderer,
+ gfloat xalign)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ g_return_if_fail (xalign >= 0);
- return priv->size;
+ if (priv->xalign != xalign)
+ {
+ priv->xalign = xalign;
+ g_object_notify_by_pspec (G_OBJECT (renderer),
+ properties[PROP_XALIGN]);
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
+ }
}
/**
- * gtk_source_gutter_renderer_set_size:
+ * gtk_source_gutter_renderer_get_yalign:
* @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.
+ * Gets the "yalign" property of the #GtkSourceGutterRenderer. This may be used
+ * to adjust where within the cell rectangle the renderer will draw.
*
- **/
-void
-gtk_source_gutter_renderer_set_size (GtkSourceGutterRenderer *renderer,
- gint size)
+ * Since: 5.0
+ */
+gfloat
+gtk_source_gutter_renderer_get_yalign (GtkSourceGutterRenderer *renderer)
{
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
+
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), 0);
- set_size (renderer, size);
+ return priv->yalign;
}
/**
- * gtk_source_gutter_renderer_get_background:
+ * gtk_source_gutter_renderer_set_yalign:
* @renderer: a #GtkSourceGutterRenderer
- * @color: (out caller-allocates) (optional): return value for a #GdkRGBA
- *
- * Get the background color of the renderer.
+ * @yalign: the Y padding for the drawing cell
*
- * Returns: %TRUE if the background color is set, %FALSE otherwise
+ * Adjusts the "yalign" property of the #GtkSourceGutterRenderer. This may be
+ * used to adjust where within the cell rectangle the renderer will draw.
*
- **/
-gboolean
-gtk_source_gutter_renderer_get_background (GtkSourceGutterRenderer *renderer,
- GdkRGBA *color)
+ * Since: 5.0
+ */
+void
+gtk_source_gutter_renderer_set_yalign (GtkSourceGutterRenderer *renderer,
+ gfloat yalign)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), FALSE);
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ g_return_if_fail (yalign >= 0);
- if (color)
+ if (priv->yalign != yalign)
{
- *color = priv->background_color;
+ priv->yalign = yalign;
+ g_object_notify_by_pspec (G_OBJECT (renderer),
+ properties[PROP_YALIGN]);
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
}
-
- return priv->background_set;
}
/**
- * gtk_source_gutter_renderer_set_background:
+ * gtk_source_gutter_renderer_get_buffer:
* @renderer: a #GtkSourceGutterRenderer
- * @color: (nullable): a #GdkRGBA or %NULL
*
- * Set the background color of the renderer. If @color is set to %NULL, the
- * renderer will not have a background color.
+ * Gets the #GtkSourceBuffer for which the gutter renderer is drawing.
+ *
+ * Returns: (transfer none) (nullable): a #GtkTextBuffer or %NULL
*
+ * Since: 5.0
*/
-void
-gtk_source_gutter_renderer_set_background (GtkSourceGutterRenderer *renderer,
- const GdkRGBA *color)
+GtkSourceBuffer *
+gtk_source_gutter_renderer_get_buffer (GtkSourceGutterRenderer *renderer)
{
- g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- set_background_color (renderer, color);
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer), NULL);
+
+ return priv->buffer;
}
void
-_gtk_source_gutter_renderer_set_view (GtkSourceGutterRenderer *renderer,
- GtkTextView *view,
- GtkTextWindowType window_type)
+_gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines)
{
GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- GtkTextView *old_view;
-
g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
- g_return_if_fail (view == NULL || GTK_IS_TEXT_VIEW (view));
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_LINES (lines));
- old_view = priv->view;
-
- priv->window_type = window_type;
- priv->view = view != NULL ? g_object_ref (view) : NULL;
+ g_set_object (&priv->lines, lines);
+ GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->begin (renderer, lines);
+}
- if (GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_view)
- {
- GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->change_view (renderer,
- old_view);
- }
+void
+_gtk_source_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+ GtkSourceGutterRendererPrivate *priv = gtk_source_gutter_renderer_get_instance_private (renderer);
- if (old_view)
- {
- g_object_unref (old_view);
- }
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER (renderer));
- g_object_notify (G_OBJECT (renderer), "view");
- g_object_notify (G_OBJECT (renderer), "window_type");
+ GTK_SOURCE_GUTTER_RENDERER_GET_CLASS (renderer)->end (renderer);
+ g_clear_object (&priv->lines);
}
diff --git a/gtksourceview/gtksourcegutterrenderer.h b/gtksourceview/gtksourcegutterrenderer.h
index baa413d5..fb38cc22 100644
--- a/gtksourceview/gtksourcegutterrenderer.h
+++ b/gtksourceview/gtksourcegutterrenderer.h
@@ -32,24 +32,6 @@ G_BEGIN_DECLS
#define GTK_SOURCE_TYPE_GUTTER_RENDERER (gtk_source_gutter_renderer_get_type())
-/**
- * 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 _GtkSourceGutterRendererState
-{
- 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;
-
/**
* GtkSourceGutterRendererAlignmentMode:
* @GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL: The full cell.
@@ -63,31 +45,23 @@ typedef enum _GtkSourceGutterRendererAlignmentMode
{
GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
- GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST
+ GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST,
} GtkSourceGutterRendererAlignmentMode;
struct _GtkSourceGutterRendererClass
{
- GInitiallyUnownedClass parent_class;
-
- /*< public >*/
- void (*begin) (GtkSourceGutterRenderer *renderer,
- cairo_t *cr,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end);
-
- void (*draw) (GtkSourceGutterRenderer *renderer,
- cairo_t *cr,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state);
-
- void (*end) (GtkSourceGutterRenderer *renderer);
-
+ GtkWidgetClass parent_class;
+
+ void (*query_data) (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines,
+ guint line);
+ void (*begin) (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines);
+ void (*snapshot_line) (GtkSourceGutterRenderer *renderer,
+ GtkSnapshot *snapshot,
+ GtkSourceGutterLines *lines,
+ guint line);
+ void (*end) (GtkSourceGutterRenderer *renderer);
/**
* GtkSourceGutterRendererClass::change_view:
* @renderer: a #GtkSourceGutterRenderer.
@@ -95,9 +69,8 @@ struct _GtkSourceGutterRendererClass
*
* This is called when the text view changes for @renderer.
*/
- void (*change_view) (GtkSourceGutterRenderer *renderer,
- GtkTextView *old_view);
-
+ void (*change_view) (GtkSourceGutterRenderer *renderer,
+ GtkSourceView *old_view);
/**
* GtkSourceGutterRendererClass::change_buffer:
* @renderer: a #GtkSourceGutterRenderer.
@@ -105,122 +78,72 @@ struct _GtkSourceGutterRendererClass
*
* This is called when the text buffer changes for @renderer.
*/
- void (*change_buffer) (GtkSourceGutterRenderer *renderer,
- GtkTextBuffer *old_buffer);
-
+ void (*change_buffer) (GtkSourceGutterRenderer *renderer,
+ GtkSourceBuffer *old_buffer);
/* Signal handlers */
- gboolean (*query_activatable) (GtkSourceGutterRenderer *renderer,
- GtkTextIter *iter,
- GdkRectangle *area,
- GdkEvent *event);
-
- void (*activate) (GtkSourceGutterRenderer *renderer,
- GtkTextIter *iter,
- GdkRectangle *area,
- GdkEvent *event);
-
- void (*queue_draw) (GtkSourceGutterRenderer *renderer);
-
- gboolean (*query_tooltip) (GtkSourceGutterRenderer *renderer,
- GtkTextIter *iter,
- GdkRectangle *area,
- gint x,
- gint y,
- GtkTooltip *tooltip);
-
- void (*query_data) (GtkSourceGutterRenderer *renderer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state);
+ gboolean (*query_activatable) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ GdkRectangle *area);
+ void (*activate) (GtkSourceGutterRenderer *renderer,
+ GtkTextIter *iter,
+ GdkRectangle *area,
+ guint button,
+ GdkModifierType state,
+ gint n_presses);
/*< private >*/
gpointer _reserved[20];
};
GTK_SOURCE_AVAILABLE_IN_ALL
-G_DECLARE_DERIVABLE_TYPE (GtkSourceGutterRenderer, gtk_source_gutter_renderer, GTK_SOURCE, GUTTER_RENDERER,
GInitiallyUnowned)
+G_DECLARE_DERIVABLE_TYPE (GtkSourceGutterRenderer, gtk_source_gutter_renderer, GTK_SOURCE, GUTTER_RENDERER,
GtkWidget)
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_begin (GtkSourceGutterRenderer
*renderer,
- cairo_t
*cr,
- GdkRectangle
*background_area,
- GdkRectangle
*cell_area,
- GtkTextIter
*start,
- GtkTextIter
*end);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_draw (GtkSourceGutterRenderer
*renderer,
- cairo_t
*cr,
- GdkRectangle
*background_area,
- GdkRectangle
*cell_area,
- GtkTextIter
*start,
- GtkTextIter
*end,
-
GtkSourceGutterRendererState state);
+gfloat gtk_source_gutter_renderer_get_xalign (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_end (GtkSourceGutterRenderer
*renderer);
+void gtk_source_gutter_renderer_set_xalign (GtkSourceGutterRenderer
*renderer,
+ gfloat
xalign);
GTK_SOURCE_AVAILABLE_IN_ALL
-gint gtk_source_gutter_renderer_get_size (GtkSourceGutterRenderer
*renderer);
+gfloat gtk_source_gutter_renderer_get_yalign (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_set_size (GtkSourceGutterRenderer
*renderer,
- gint
size);
+void gtk_source_gutter_renderer_set_yalign (GtkSourceGutterRenderer
*renderer,
+ gfloat
yalign);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_set_visible (GtkSourceGutterRenderer
*renderer,
- gboolean
visible);
+gint gtk_source_gutter_renderer_get_xpad (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_gutter_renderer_get_visible (GtkSourceGutterRenderer
*renderer);
+void gtk_source_gutter_renderer_set_xpad (GtkSourceGutterRenderer
*renderer,
+ gint
xpad);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_get_padding (GtkSourceGutterRenderer
*renderer,
- gint
*xpad,
- gint
*ypad);
+gint gtk_source_gutter_renderer_get_ypad (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_set_padding (GtkSourceGutterRenderer
*renderer,
- gint
xpad,
+void gtk_source_gutter_renderer_set_ypad (GtkSourceGutterRenderer
*renderer,
gint
ypad);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_get_alignment (GtkSourceGutterRenderer
*renderer,
- gfloat
*xalign,
- gfloat
*yalign);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_set_alignment (GtkSourceGutterRenderer
*renderer,
- gfloat
xalign,
- gfloat
yalign);
+GtkSourceGutterRendererAlignmentMode gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
void gtk_source_gutter_renderer_set_alignment_mode (GtkSourceGutterRenderer
*renderer,
GtkSourceGutterRendererAlignmentMode mode);
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkTextWindowType gtk_source_gutter_renderer_get_window_type (GtkSourceGutterRenderer
*renderer);
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkTextView *gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer
*renderer);
-GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceGutterRendererAlignmentMode gtk_source_gutter_renderer_get_alignment_mode (GtkSourceGutterRenderer
*renderer);
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_gutter_renderer_get_background (GtkSourceGutterRenderer
*renderer,
- GdkRGBA
*color);
+GtkSourceBuffer *gtk_source_gutter_renderer_get_buffer (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_set_background (GtkSourceGutterRenderer
*renderer,
- const GdkRGBA
*color);
+GtkSourceView *gtk_source_gutter_renderer_get_view (GtkSourceGutterRenderer
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
void gtk_source_gutter_renderer_activate (GtkSourceGutterRenderer
*renderer,
- GtkTextIter
*iter,
- GdkRectangle
*area,
- GdkEvent
*event);
+ const GtkTextIter
*iter,
+ const GdkRectangle
*area,
+ guint
button,
+ GdkModifierType
state,
+ gint
n_presses);
GTK_SOURCE_AVAILABLE_IN_ALL
gboolean gtk_source_gutter_renderer_query_activatable (GtkSourceGutterRenderer
*renderer,
- GtkTextIter
*iter,
- GdkRectangle
*area,
- GdkEvent
*event);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_queue_draw (GtkSourceGutterRenderer
*renderer);
-GTK_SOURCE_AVAILABLE_IN_ALL
-gboolean gtk_source_gutter_renderer_query_tooltip (GtkSourceGutterRenderer
*renderer,
- GtkTextIter
*iter,
- GdkRectangle
*area,
- gint
x,
- gint
y,
- GtkTooltip
*tooltip);
-GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_query_data (GtkSourceGutterRenderer
*renderer,
- GtkTextIter
*start,
- GtkTextIter
*end,
-
GtkSourceGutterRendererState state);
+ const GtkTextIter
*iter,
+ const GdkRectangle
*area);
+GTK_SOURCE_AVAILABLE_IN_ALL
+void gtk_source_gutter_renderer_align_cell (GtkSourceGutterRenderer
*renderer,
+ guint
line,
+ gfloat
width,
+ gfloat
height,
+ gfloat
*x,
+ gfloat
*y);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutterrendererlines.c b/gtksourceview/gtksourcegutterrendererlines.c
index 6f508ce1..07e06423 100644
--- a/gtksourceview/gtksourcegutterrendererlines.c
+++ b/gtksourceview/gtksourcegutterrendererlines.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "gtksourcegutterrendererlines-private.h"
+#include "gtksourcegutterlines.h"
#include "gtksourceutils-private.h"
#include "gtksourceview.h"
@@ -34,16 +35,6 @@ struct _GtkSourceGutterRendererLines
G_DEFINE_TYPE (GtkSourceGutterRendererLines, _gtk_source_gutter_renderer_lines,
GTK_SOURCE_TYPE_GUTTER_RENDERER_TEXT)
-static GtkTextBuffer *
-get_buffer (GtkSourceGutterRendererLines *renderer)
-{
- GtkTextView *view;
-
- view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (renderer));
-
- return view != NULL ? gtk_text_view_get_buffer (view) : NULL;
-}
-
static inline gint
count_num_digits (gint num_lines)
{
@@ -76,33 +67,18 @@ count_num_digits (gint num_lines)
static void
recalculate_size (GtkSourceGutterRendererLines *renderer)
{
+ GtkSourceBuffer *buffer;
gint num_lines;
- gint num_digits = 0;
- GtkTextBuffer *buffer;
-
- buffer = get_buffer (renderer);
-
- num_lines = gtk_text_buffer_get_line_count (buffer);
+ gint num_digits;
+ buffer = gtk_source_gutter_renderer_get_buffer (GTK_SOURCE_GUTTER_RENDERER (renderer));
+ num_lines = gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (buffer));
num_digits = count_num_digits (num_lines);
if (num_digits != renderer->num_line_digits)
{
- gchar markup[24];
- gint size;
-
renderer->num_line_digits = num_digits;
-
- num_lines = MAX (num_lines, 99);
-
- g_snprintf (markup, sizeof markup, "<b>%d</b>", num_lines);
- gtk_source_gutter_renderer_text_measure_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
- markup,
- &size,
- NULL);
-
- gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (renderer),
- size);
+ gtk_widget_queue_resize (GTK_WIDGET (renderer));
}
}
@@ -113,21 +89,37 @@ on_buffer_changed (GtkSourceBuffer *buffer,
recalculate_size (renderer);
}
+static void
+on_buffer_cursor_moved (GtkSourceBuffer *buffer,
+ GtkSourceGutterRendererLines *renderer)
+{
+ if (renderer->cursor_visible)
+ {
+ /* Redraw if the current-line needs updating */
+ gtk_widget_queue_draw (GTK_WIDGET (renderer));
+ }
+}
+
static void
gutter_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
- GtkTextBuffer *old_buffer)
+ GtkSourceBuffer *old_buffer)
{
GtkSourceGutterRendererLines *lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
- GtkTextBuffer *buffer;
+ GtkSourceBuffer *buffer;
if (old_buffer != NULL)
{
g_signal_handlers_disconnect_by_func (old_buffer,
on_buffer_changed,
lines);
+ g_signal_handlers_disconnect_by_func (old_buffer,
+ on_buffer_cursor_moved,
+ lines);
}
- buffer = get_buffer (lines);
+ buffer = gtk_source_gutter_renderer_get_buffer (renderer);
+
+ lines->prev_line_num = 0;
if (buffer != NULL)
{
@@ -137,20 +129,21 @@ gutter_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
lines,
0);
+ g_signal_connect_object (buffer,
+ "cursor-moved",
+ G_CALLBACK (on_buffer_cursor_moved),
+ lines,
+ 0);
+
recalculate_size (lines);
}
- lines->prev_line_num = 0;
-
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->change_buffer
!= NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS
(_gtk_source_gutter_renderer_lines_parent_class)->change_buffer (renderer, old_buffer);
- }
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->change_buffer
(renderer, old_buffer);
}
static void
on_view_style_updated (GtkTextView *view,
- GtkSourceGutterRendererLines *renderer)
+ GtkSourceGutterRendererLines *renderer)
{
/* Force to recalculate the size. */
renderer->num_line_digits = -1;
@@ -167,9 +160,9 @@ on_view_notify_cursor_visible (GtkTextView *view,
static void
gutter_renderer_change_view (GtkSourceGutterRenderer *renderer,
- GtkTextView *old_view)
+ GtkSourceView *old_view)
{
- GtkTextView *new_view;
+ GtkSourceView *new_view;
if (old_view != NULL)
{
@@ -197,116 +190,10 @@ gutter_renderer_change_view (GtkSourceGutterRenderer *renderer,
renderer,
0);
- GTK_SOURCE_GUTTER_RENDERER_LINES (renderer)->cursor_visible =
gtk_text_view_get_cursor_visible (new_view);
- }
-
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->change_view !=
NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS
(_gtk_source_gutter_renderer_lines_parent_class)->change_view (renderer, old_view);
- }
-}
-
-static void
-gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
-{
- GtkSourceGutterRendererLines *lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
- gchar text[24];
- const gchar *textptr = text;
- gint line;
- gint len;
- gboolean current_line;
-
- line = gtk_text_iter_get_line (start) + 1;
-
- current_line = (state & GTK_SOURCE_GUTTER_RENDERER_STATE_CURSOR) &&
- lines->cursor_visible;
-
- if G_LIKELY (!current_line)
- {
- len = _gtk_source_utils_int_to_string (line, &textptr);
- }
- else
- {
- len = g_snprintf (text, sizeof text, "<b>%d</b>", line);
- }
-
- gtk_source_gutter_renderer_text_set_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
- textptr,
- len);
-}
-
-static gint
-get_last_visible_line_number (GtkSourceGutterRendererLines *lines)
-{
- GtkTextView *view;
- GdkRectangle visible_rect;
- GtkTextIter iter;
-
- view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (lines));
-
- gtk_text_view_get_visible_rect (view, &visible_rect);
-
- gtk_text_view_get_line_at_y (view,
- &iter,
- visible_rect.y + visible_rect.height,
- NULL);
-
- gtk_text_iter_forward_line (&iter);
-
- return gtk_text_iter_get_line (&iter);
-}
-
-static void
-gutter_renderer_end (GtkSourceGutterRenderer *renderer)
-{
- GtkSourceGutterRendererLines *lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
- GtkTextBuffer *buffer = get_buffer (lines);
-
- if (buffer != NULL)
- {
- gint line_num = get_last_visible_line_number (lines);
-
- /* When the text is modified in a GtkTextBuffer, GtkTextView tries to
- * redraw the smallest required region. But the information displayed in
- * the gutter may become invalid in a bigger region.
- * See https://bugzilla.gnome.org/show_bug.cgi?id=732418 for an example
- * where line numbers are not updated correctly when splitting a wrapped
- * line.
- * The performances should not be a big problem here. Correctness is
- * more important than performances. It just triggers a second
- * draw.
- * The queue_draw() is called in gutter_renderer_end(), because
- * the first draw is anyway needed to avoid flickering (if the
- * first draw is not done, there will be a white region in the
- * gutter during one frame).
- * Another solution that has better performances is to compare
- * the total number of lines in the buffer, instead of the last
- * visible line. But it has the drawback that the gutter is
- * continuously redrawn during file loading.
- *
- * FIXME A better solution would be to add a vfunc in the
- * GutterRenderer so that the Gutter can ask each renderer for
- * the invalidation region, before drawing. So that only one
- * draw is needed, and the solution would be more generic (if
- * other renderers also need a different invalidation region
- * than the GtkTextView). But the GutterRendererClass doesn't
- * have padding for future expansion, so it must wait for
- * GtkSourceView 4.
- */
- if (lines->prev_line_num != line_num)
- {
- lines->prev_line_num = line_num;
- gtk_source_gutter_renderer_queue_draw (renderer);
- }
+ GTK_SOURCE_GUTTER_RENDERER_LINES (renderer)->cursor_visible =
gtk_text_view_get_cursor_visible (GTK_TEXT_VIEW (new_view));
}
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->end != NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->end
(renderer);
- }
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (_gtk_source_gutter_renderer_lines_parent_class)->change_view
(renderer, old_view);
}
static void
@@ -316,11 +203,11 @@ extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
GtkTextIter start;
GtkTextIter end;
GtkTextIter line_end;
- GtkTextBuffer *buffer;
+ GtkSourceBuffer *buffer;
- buffer = get_buffer (renderer);
+ buffer = gtk_source_gutter_renderer_get_buffer (GTK_SOURCE_GUTTER_RENDERER (renderer));
- gtk_text_buffer_get_selection_bounds (buffer,
+ gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (buffer),
&start,
&end);
@@ -333,7 +220,7 @@ extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
if (gtk_text_iter_compare (&start, line_start) < 0)
{
- gtk_text_buffer_select_range (buffer,
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
&start,
&line_end);
}
@@ -341,13 +228,13 @@ extend_selection_to_line (GtkSourceGutterRendererLines *renderer,
{
/* if the selection is in this line, extend
* the selection to the whole line */
- gtk_text_buffer_select_range (buffer,
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
&line_end,
line_start);
}
else
{
- gtk_text_buffer_select_range (buffer,
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer),
&end,
line_start);
}
@@ -358,9 +245,9 @@ select_line (GtkSourceGutterRendererLines *renderer,
GtkTextIter *line_start)
{
GtkTextIter iter;
- GtkTextBuffer *buffer;
+ GtkSourceBuffer *buffer;
- buffer = get_buffer (renderer);
+ buffer = gtk_source_gutter_renderer_get_buffer (GTK_SOURCE_GUTTER_RENDERER (renderer));
iter = *line_start;
@@ -370,31 +257,37 @@ select_line (GtkSourceGutterRendererLines *renderer,
}
/* Select the line, put the cursor at the end of the line */
- gtk_text_buffer_select_range (buffer, &iter, line_start);
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, line_start);
}
static void
gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
GtkTextIter *iter,
GdkRectangle *rect,
- GdkEvent *event)
+ guint button,
+ GdkModifierType state,
+ gint n_presses)
{
GtkSourceGutterRendererLines *lines;
+ GtkSourceBuffer *buffer;
lines = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
- if (event->type == GDK_BUTTON_PRESS && (event->button.button == 1))
+ if (button != 1)
{
- GtkTextBuffer *buffer;
+ return;
+ }
- buffer = get_buffer (lines);
+ buffer = gtk_source_gutter_renderer_get_buffer (renderer);
- if ((event->button.state & GDK_CONTROL_MASK) != 0)
+ if (n_presses == 1)
+ {
+ if ((state & GDK_CONTROL_MASK) != 0)
{
/* Single click + Ctrl -> select the line */
select_line (lines, iter);
}
- else if ((event->button.state & GDK_SHIFT_MASK) != 0)
+ else if ((state & GDK_SHIFT_MASK) != 0)
{
/* Single click + Shift -> extended current
selection to include the clicked line */
@@ -402,10 +295,10 @@ gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
}
else
{
- gtk_text_buffer_place_cursor (buffer, iter);
+ gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (buffer), iter);
}
}
- else if (event->type == GDK_2BUTTON_PRESS && (event->button.button == 1))
+ else if (n_presses == 2)
{
select_line (lines, iter);
}
@@ -414,20 +307,87 @@ gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
static gboolean
gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
GtkTextIter *iter,
- GdkRectangle *area,
- GdkEvent *event)
+ GdkRectangle *area)
+{
+ return gtk_source_gutter_renderer_get_buffer (renderer) != NULL;
+}
+
+static void
+gtk_source_gutter_renderer_lines_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkSourceGutterRendererLines *renderer = GTK_SOURCE_GUTTER_RENDERER_LINES (widget);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ *minimum = 0;
+ *natural = 0;
+ }
+ else
+ {
+ GtkSourceBuffer *buffer;
+ gchar markup[32];
+ guint num_lines;
+ gint size;
+ gint xpad;
+
+ buffer = gtk_source_gutter_renderer_get_buffer (GTK_SOURCE_GUTTER_RENDERER (renderer));
+ num_lines = MAX (99, gtk_text_buffer_get_line_count (GTK_TEXT_BUFFER (buffer)));
+
+ g_snprintf (markup, sizeof markup, "<b>%u</b>", num_lines);
+ gtk_source_gutter_renderer_text_measure_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer),
+ markup,
+ &size,
+ NULL);
+
+ xpad = gtk_source_gutter_renderer_get_xpad (GTK_SOURCE_GUTTER_RENDERER (renderer));
+
+ *natural = *minimum = size + xpad * 2;
+ }
+
+ *minimum_baseline = -1;
+ *natural_baseline = -1;
+}
+
+static void
+gtk_source_gutter_renderer_lines_query_data (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines,
+ guint line)
{
- return get_buffer (GTK_SOURCE_GUTTER_RENDERER_LINES (renderer)) != NULL;
+ GtkSourceGutterRendererLines *self = GTK_SOURCE_GUTTER_RENDERER_LINES (renderer);
+ gint len;
+
+ if G_UNLIKELY (self->cursor_visible && gtk_source_gutter_lines_is_cursor (lines, line))
+ {
+ gchar text[32];
+
+ len = g_snprintf (text, sizeof text, "<b>%d</b>", line + 1);
+ gtk_source_gutter_renderer_text_set_markup (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer), text,
len);
+ }
+ else
+ {
+ const gchar *text;
+
+ len = _gtk_source_utils_int_to_string (line + 1, &text);
+ gtk_source_gutter_renderer_text_set_text (GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer), text,
len);
+ }
}
static void
_gtk_source_gutter_renderer_lines_class_init (GtkSourceGutterRendererLinesClass *klass)
{
GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->measure = gtk_source_gutter_renderer_lines_measure;
- renderer_class->query_data = gutter_renderer_query_data;
- renderer_class->end = gutter_renderer_end;
renderer_class->query_activatable = gutter_renderer_query_activatable;
+ renderer_class->query_data = gtk_source_gutter_renderer_lines_query_data;
renderer_class->activate = gutter_renderer_activate;
renderer_class->change_buffer = gutter_renderer_change_buffer;
renderer_class->change_view = gutter_renderer_change_view;
diff --git a/gtksourceview/gtksourcegutterrenderermarks.c b/gtksourceview/gtksourcegutterrenderermarks.c
index 70f9d508..0c9dbf6d 100644
--- a/gtksourceview/gtksourcegutterrenderermarks.c
+++ b/gtksourceview/gtksourcegutterrenderermarks.c
@@ -96,28 +96,23 @@ measure_line_height (GtkSourceView *view)
return height - 2;
}
-static GdkPixbuf *
-composite_marks (GtkSourceView *view,
- GSList *marks,
- gint size)
+static void
+composite_marks (GtkSourceView *view,
+ GtkSourceGutterRendererPixbuf *renderer,
+ 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;
+ gtk_source_gutter_renderer_pixbuf_set_paintable (renderer, NULL);
/* composite all the pixbufs for the marks present at the line */
do
{
GtkSourceMark *mark;
GtkSourceMarkAttributes *attrs;
- const GdkPixbuf *pixbuf;
+ GdkPaintable *paintable;
mark = marks->data;
attrs = gtk_source_view_get_mark_attributes (view,
@@ -129,81 +124,53 @@ composite_marks (GtkSourceView *view,
continue;
}
- pixbuf = gtk_source_mark_attributes_render_icon (attrs,
- GTK_WIDGET (view),
- size);
+ paintable = gtk_source_mark_attributes_render_icon (attrs,
+ GTK_WIDGET (view),
+ size);
- if (pixbuf != NULL)
+ if (paintable != 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);
- }
+ gtk_source_gutter_renderer_pixbuf_overlay_paintable (renderer, paintable);
}
marks = g_slist_next (marks);
}
while (marks);
-
- return composite;
}
static void
-gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
+gutter_renderer_query_data (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines,
+ guint line)
{
- GSList *marks;
- GdkPixbuf *pixbuf = NULL;
- gint size = 0;
- GtkSourceView *view;
GtkSourceBuffer *buffer;
+ GtkSourceView *view;
+ GtkTextIter iter;
+ GSList *marks;
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);
+ gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &iter, line);
+ marks = gtk_source_buffer_get_source_marks_at_iter (buffer, &iter, NULL);
if (marks != NULL)
{
- size = measure_line_height (view);
- pixbuf = composite_marks (view, marks, size);
-
+ gint size = measure_line_height (view);
+ composite_marks (view, GTK_SOURCE_GUTTER_RENDERER_PIXBUF (renderer), marks, size);
+ g_object_set (G_OBJECT (renderer),
+ "xpad", 2,
+ "yalign", 0.5,
+ "xalign", 0.5,
+ "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ NULL);
g_slist_free (marks);
}
-
- g_object_set (G_OBJECT (renderer),
- "pixbuf", pixbuf,
- "xpad", 2,
- "yalign", 0.5,
- "xalign", 0.5,
- "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
- NULL);
-
- g_clear_object (&pixbuf);
+ else
+ {
+ gtk_source_gutter_renderer_pixbuf_set_paintable (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (renderer),
+ NULL);
+ }
}
static gboolean
@@ -211,11 +178,9 @@ set_tooltip_widget_from_marks (GtkSourceView *view,
GtkTooltip *tooltip,
GSList *marks)
{
+ const gint icon_size = 16;
GtkGrid *grid = NULL;
gint row_num = 0;
- gint icon_size;
-
- gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size);
for (; marks; marks = g_slist_next (marks))
{
@@ -225,7 +190,7 @@ set_tooltip_widget_from_marks (GtkSourceView *view,
gchar *text;
gboolean ismarkup = FALSE;
GtkWidget *label;
- const GdkPixbuf *pixbuf;
+ GdkPaintable *paintable;
mark = marks->data;
category = gtk_source_mark_get_category (mark);
@@ -275,23 +240,19 @@ set_tooltip_widget_from_marks (GtkSourceView *view,
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_widget_show (label);
- pixbuf = gtk_source_mark_attributes_render_icon (attrs,
- GTK_WIDGET (view),
- icon_size);
+ paintable = gtk_source_mark_attributes_render_icon (attrs,
+ GTK_WIDGET (view),
+ icon_size);
- if (pixbuf == NULL)
+ if (paintable == NULL)
{
gtk_grid_attach (grid, label, 0, row_num, 2, 1);
}
else
{
GtkWidget *image;
- GdkPixbuf *copy;
- /* FIXME why a copy is needed? */
- copy = gdk_pixbuf_copy (pixbuf);
- image = gtk_image_new_from_pixbuf (copy);
- g_object_unref (copy);
+ image = gtk_image_new_from_paintable (paintable);
gtk_widget_set_halign (image, GTK_ALIGN_START);
gtk_widget_set_valign (image, GTK_ALIGN_START);
@@ -329,24 +290,26 @@ set_tooltip_widget_from_marks (GtkSourceView *view,
}
static gboolean
-gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
- GtkTextIter *iter,
- GdkRectangle *area,
- gint x,
- gint y,
- GtkTooltip *tooltip)
+gutter_renderer_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard,
+ GtkTooltip *tooltip)
{
+ GtkSourceGutterRenderer *renderer;
GSList *marks;
GtkSourceView *view;
GtkSourceBuffer *buffer;
+ GtkTextIter iter;
gboolean ret;
+ renderer = GTK_SOURCE_GUTTER_RENDERER (widget);
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);
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, 0, y);
+
+ marks = gtk_source_buffer_get_source_marks_at_iter (buffer, &iter, NULL);
if (marks != NULL)
{
@@ -369,24 +332,24 @@ gutter_renderer_query_tooltip (GtkSourceGutterRenderer *renderer,
static gboolean
gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
GtkTextIter *iter,
- GdkRectangle *area,
- GdkEvent *event)
+ GdkRectangle *area)
{
return TRUE;
}
static void
gutter_renderer_change_view (GtkSourceGutterRenderer *renderer,
- GtkTextView *old_view)
+ GtkSourceView *old_view)
{
GtkSourceView *view;
- view = GTK_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+ view = gtk_source_gutter_renderer_get_view (renderer);
if (view != NULL)
{
- gtk_source_gutter_renderer_set_size (renderer,
- measure_line_height (view));
+ gtk_widget_set_size_request (GTK_WIDGET (renderer),
+ measure_line_height (view),
+ -1);
}
if (GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_marks_parent_class)->change_view !=
NULL)
@@ -400,9 +363,11 @@ static void
gtk_source_gutter_renderer_marks_class_init (GtkSourceGutterRendererMarksClass *klass)
{
GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->query_tooltip = gutter_renderer_query_tooltip;
renderer_class->query_data = gutter_renderer_query_data;
- renderer_class->query_tooltip = gutter_renderer_query_tooltip;
renderer_class->query_activatable = gutter_renderer_query_activatable;
renderer_class->change_view = gutter_renderer_change_view;
}
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.c b/gtksourceview/gtksourcegutterrendererpixbuf.c
index 46026886..b7db4bae 100644
--- a/gtksourceview/gtksourcegutterrendererpixbuf.c
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.c
@@ -36,6 +36,8 @@
typedef struct
{
GtkSourcePixbufHelper *helper;
+ GdkPaintable *paintable;
+ GPtrArray *overlays;
} GtkSourceGutterRendererPixbufPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceGutterRendererPixbuf, gtk_source_gutter_renderer_pixbuf,
GTK_SOURCE_TYPE_GUTTER_RENDERER)
@@ -46,147 +48,80 @@ enum
PROP_PIXBUF,
PROP_ICON_NAME,
PROP_GICON,
+ PROP_PAINTABLE,
};
static void
-center_on (GtkSourceGutterRenderer *renderer,
- GdkRectangle *cell_area,
- GtkTextIter *iter,
- gint width,
- gint height,
- gfloat xalign,
- gfloat yalign,
- gint *x,
- gint *y)
+clear_overlays (GtkSourceGutterRendererPixbuf *renderer)
{
- GtkTextView *view;
- GtkTextWindowType window_type;
- GdkRectangle buffer_location;
- gint window_y;
-
- view = gtk_source_gutter_renderer_get_view (renderer);
- window_type = gtk_source_gutter_renderer_get_window_type (renderer);
-
- gtk_text_view_get_iter_location (view, iter, &buffer_location);
-
- gtk_text_view_buffer_to_window_coords (view,
- window_type,
- 0, buffer_location.y,
- NULL, &window_y);
+ GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
- *x = cell_area->x + (cell_area->width - width) * xalign;
- *y = window_y + (buffer_location.height - height) * yalign;
+ if (priv->overlays != NULL && priv->overlays->len > 0)
+ {
+ g_ptr_array_remove_range (priv->overlays, 0, priv->overlays->len);
+ }
}
static void
-gutter_renderer_pixbuf_draw (GtkSourceGutterRenderer *renderer,
- cairo_t *cr,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
+gutter_renderer_pixbuf_snapshot_line (GtkSourceGutterRenderer *renderer,
+ GtkSnapshot *snapshot,
+ GtkSourceGutterLines *lines,
+ guint line)
{
GtkSourceGutterRendererPixbuf *pix = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (renderer);
GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(pix);
+ GtkWidget *widget = GTK_WIDGET (renderer);
+ GdkPaintable *paintable;
+ GtkSourceView *view;
gint width;
gint height;
- gfloat xalign;
- gfloat yalign;
- GtkSourceGutterRendererAlignmentMode mode;
- GtkTextView *view;
- gint scale;
- gint x = 0;
- gint y = 0;
- GdkPixbuf *pixbuf;
- cairo_surface_t *surface;
-
- /* Chain up to draw background */
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_pixbuf_parent_class)->draw != NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_pixbuf_parent_class)->draw
(renderer,
- cr,
-
background_area,
-
cell_area,
-
start,
- end,
-
state);
- }
+ gfloat x = 0;
+ gfloat y = 0;
+ guint i;
+ gint size;
view = gtk_source_gutter_renderer_get_view (renderer);
- pixbuf = gtk_source_pixbuf_helper_render (priv->helper,
- GTK_WIDGET (view),
- cell_area->width);
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_height (widget);
+ size = MIN (width, height);
- if (!pixbuf)
- {
- return;
- }
+ paintable = gtk_source_pixbuf_helper_render (priv->helper,
+ GTK_WIDGET (view),
+ size);
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
-
- /*
- * We might have gotten a pixbuf back from the helper that will allow
- * us to render for HiDPI. If we detect this, we pretend that we got a
- * different size back and then gdk_cairo_surface_create_from_pixbuf()
- * will take care of the rest.
- */
- scale = gtk_widget_get_scale_factor (GTK_WIDGET (view));
- if ((scale > 1) &&
- ((width > cell_area->width) || (height > cell_area->height)) &&
- (width <= (cell_area->width * scale)) &&
- (height <= (cell_area->height * scale)))
+ /* Short-circuit if there is nothing to snapshot */
+ if (paintable == NULL &&
+ (priv->overlays == NULL || priv->overlays->len == 0))
{
- width = width / scale;
- height = height / scale;
+ return;
}
- gtk_source_gutter_renderer_get_alignment (renderer,
- &xalign,
- &yalign);
+ gtk_source_gutter_renderer_align_cell (renderer, line, size, size, &x, &y);
- mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
- switch (mode)
+ if (paintable != NULL)
{
- 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;
- default:
- g_assert_not_reached ();
+ gdk_paintable_snapshot (paintable, snapshot, size, size);
+ }
+ else if (priv->paintable != NULL)
+ {
+ gdk_paintable_snapshot (priv->paintable, snapshot, size, size);
}
- surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, NULL);
- cairo_set_source_surface (cr, surface, x, y);
+ if (priv->overlays != NULL)
+ {
+ for (i = 0; i < priv->overlays->len; i++)
+ {
+ GdkPaintable *ele = g_ptr_array_index (priv->overlays, i);
- cairo_paint (cr);
+ gdk_paintable_snapshot (ele, snapshot, size, size);
+ }
+ }
- cairo_surface_destroy (surface);
+ gtk_snapshot_restore (snapshot);
}
static void
@@ -195,7 +130,8 @@ gtk_source_gutter_renderer_pixbuf_finalize (GObject *object)
GtkSourceGutterRendererPixbuf *renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
- gtk_source_pixbuf_helper_free (priv->helper);
+ g_clear_pointer (&priv->helper, gtk_source_pixbuf_helper_free);
+ g_clear_pointer (&priv->overlays, g_ptr_array_unref);
G_OBJECT_CLASS (gtk_source_gutter_renderer_pixbuf_parent_class)->finalize (object);
}
@@ -206,11 +142,9 @@ set_pixbuf (GtkSourceGutterRendererPixbuf *renderer,
{
GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+ g_clear_object (&priv->paintable);
+ clear_overlays (renderer);
gtk_source_pixbuf_helper_set_pixbuf (priv->helper, pixbuf);
-
- g_object_notify (G_OBJECT (renderer), "pixbuf");
-
- gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
}
static void
@@ -219,11 +153,9 @@ set_gicon (GtkSourceGutterRendererPixbuf *renderer,
{
GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+ g_clear_object (&priv->paintable);
+ clear_overlays (renderer);
gtk_source_pixbuf_helper_set_gicon (priv->helper, icon);
-
- g_object_notify (G_OBJECT (renderer), "gicon");
-
- gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
}
static void
@@ -232,11 +164,9 @@ set_icon_name (GtkSourceGutterRendererPixbuf *renderer,
{
GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+ g_clear_object (&priv->paintable);
+ clear_overlays (renderer);
gtk_source_pixbuf_helper_set_icon_name (priv->helper, icon_name);
-
- g_object_notify (G_OBJECT (renderer), "icon-name");
-
- gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (renderer));
}
@@ -246,9 +176,7 @@ gtk_source_gutter_renderer_pixbuf_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- GtkSourceGutterRendererPixbuf *renderer;
-
- renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
+ GtkSourceGutterRendererPixbuf *renderer = GTK_SOURCE_GUTTER_RENDERER_PIXBUF (object);
switch (prop_id)
{
@@ -261,6 +189,10 @@ gtk_source_gutter_renderer_pixbuf_set_property (GObject *object,
case PROP_GICON:
set_gicon (renderer, g_value_get_object (value));
break;
+ case PROP_PAINTABLE:
+ gtk_source_gutter_renderer_pixbuf_set_paintable (renderer,
+ g_value_get_object (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -290,6 +222,9 @@ gtk_source_gutter_renderer_pixbuf_get_property (GObject *object,
g_value_set_object (value,
gtk_source_pixbuf_helper_get_gicon (priv->helper));
break;
+ case PROP_PAINTABLE:
+ g_value_set_object (value, priv->paintable);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -303,11 +238,18 @@ gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass
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;
+ renderer_class->snapshot_line = gutter_renderer_pixbuf_snapshot_line;
+
+ g_object_class_install_property (object_class,
+ PROP_PAINTABLE,
+ g_param_spec_object ("paintable",
+ "Paintable",
+ "The paintable",
+ GDK_TYPE_PAINTABLE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_PIXBUF,
@@ -315,7 +257,7 @@ gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass
"Pixbuf",
"The pixbuf",
GDK_TYPE_PIXBUF,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_ICON_NAME,
@@ -323,7 +265,7 @@ gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass
"Icon Name",
"The icon name",
NULL,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_GICON,
@@ -331,7 +273,7 @@ gtk_source_gutter_renderer_pixbuf_class_init (GtkSourceGutterRendererPixbufClass
"GIcon",
"The gicon",
G_TYPE_ICON,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS));
}
static void
@@ -448,3 +390,71 @@ gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf *
return gtk_source_pixbuf_helper_get_icon_name (priv->helper);
}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_set_paintable:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ * @paintable: (nullable): the paintable, or %NULL.
+ */
+void
+gtk_source_gutter_renderer_pixbuf_set_paintable (GtkSourceGutterRendererPixbuf *renderer,
+ GdkPaintable *paintable)
+{
+ GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER_PIXBUF (renderer));
+ g_return_if_fail (!paintable || GDK_IS_PAINTABLE (paintable));
+
+ clear_overlays (renderer);
+ gtk_source_pixbuf_helper_set_icon_name (priv->helper, NULL);
+ g_set_object (&priv->paintable, paintable);
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_get_paintable:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ *
+ * Gets a #GdkPaintable that was set with
+ * gtk_source_gutter_renderer_pixbuf_set_paintable()
+ *
+ * Returns: (transfer none) (nullable): a #GdkPaintable or %NULL
+ *
+ * Since: 5.0
+ */
+GdkPaintable *
+gtk_source_gutter_renderer_pixbuf_get_paintable (GtkSourceGutterRendererPixbuf *renderer)
+{
+ GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+
+ g_return_val_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER_PIXBUF (renderer), NULL);
+
+ return priv->paintable;
+}
+
+/**
+ * gtk_source_gutter_renderer_pixbuf_overlay_paintable:
+ * @renderer: a #GtkSourceGutterRendererPixbuf
+ * @paintable: a #GdkPaintable
+ *
+ * Allows overlaying a paintable on top of any other image that
+ * has been set for the pixbuf. This will be applied when the
+ * widget is next snapshot.
+ *
+ * Since: 5.0
+ */
+void
+gtk_source_gutter_renderer_pixbuf_overlay_paintable (GtkSourceGutterRendererPixbuf *renderer,
+ GdkPaintable *paintable)
+{
+ GtkSourceGutterRendererPixbufPrivate *priv = gtk_source_gutter_renderer_pixbuf_get_instance_private
(renderer);
+
+ g_return_if_fail (GTK_SOURCE_IS_GUTTER_RENDERER_PIXBUF (renderer));
+ g_return_if_fail (GDK_IS_PAINTABLE (paintable));
+
+ if (priv->overlays == NULL)
+ {
+ priv->overlays = g_ptr_array_new_with_free_func (g_object_unref);
+ }
+
+ g_ptr_array_add (priv->overlays, g_object_ref (paintable));
+}
diff --git a/gtksourceview/gtksourcegutterrendererpixbuf.h b/gtksourceview/gtksourcegutterrendererpixbuf.h
index ee82b6a4..5bb1f289 100644
--- a/gtksourceview/gtksourcegutterrendererpixbuf.h
+++ b/gtksourceview/gtksourcegutterrendererpixbuf.h
@@ -43,21 +43,29 @@ struct _GtkSourceGutterRendererPixbufClass
};
GTK_SOURCE_AVAILABLE_IN_ALL
-GtkSourceGutterRenderer *gtk_source_gutter_renderer_pixbuf_new (void);
+GtkSourceGutterRenderer *gtk_source_gutter_renderer_pixbuf_new (void);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_pixbuf_set_pixbuf (GtkSourceGutterRendererPixbuf
*renderer,
- GdkPixbuf
*pixbuf);
+void gtk_source_gutter_renderer_pixbuf_set_pixbuf (GtkSourceGutterRendererPixbuf
*renderer,
+ GdkPixbuf
*pixbuf);
GTK_SOURCE_AVAILABLE_IN_ALL
-GdkPixbuf *gtk_source_gutter_renderer_pixbuf_get_pixbuf (GtkSourceGutterRendererPixbuf
*renderer);
+GdkPixbuf *gtk_source_gutter_renderer_pixbuf_get_pixbuf (GtkSourceGutterRendererPixbuf
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_pixbuf_set_gicon (GtkSourceGutterRendererPixbuf
*renderer,
- GIcon
*icon);
+void gtk_source_gutter_renderer_pixbuf_set_gicon (GtkSourceGutterRendererPixbuf
*renderer,
+ GIcon
*icon);
GTK_SOURCE_AVAILABLE_IN_ALL
-GIcon *gtk_source_gutter_renderer_pixbuf_get_gicon (GtkSourceGutterRendererPixbuf
*renderer);
+GIcon *gtk_source_gutter_renderer_pixbuf_get_gicon (GtkSourceGutterRendererPixbuf
*renderer);
GTK_SOURCE_AVAILABLE_IN_ALL
-void gtk_source_gutter_renderer_pixbuf_set_icon_name (GtkSourceGutterRendererPixbuf
*renderer,
- const gchar
*icon_name);
+void gtk_source_gutter_renderer_pixbuf_set_icon_name (GtkSourceGutterRendererPixbuf
*renderer,
+ const gchar
*icon_name);
GTK_SOURCE_AVAILABLE_IN_ALL
-const gchar *gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf
*renderer);
+const gchar *gtk_source_gutter_renderer_pixbuf_get_icon_name (GtkSourceGutterRendererPixbuf
*renderer);
+GTK_SOURCE_AVAILABLE_IN_ALL
+GdkPaintable *gtk_source_gutter_renderer_pixbuf_get_paintable (GtkSourceGutterRendererPixbuf
*renderer);
+GTK_SOURCE_AVAILABLE_IN_ALL
+void gtk_source_gutter_renderer_pixbuf_set_paintable (GtkSourceGutterRendererPixbuf
*renderer,
+ GdkPaintable
*paintable);
+GTK_SOURCE_AVAILABLE_IN_ALL
+void gtk_source_gutter_renderer_pixbuf_overlay_paintable (GtkSourceGutterRendererPixbuf
*renderer,
+ GdkPaintable
*paintable);
G_END_DECLS
diff --git a/gtksourceview/gtksourcegutterrenderertext.c b/gtksourceview/gtksourcegutterrenderertext.c
index c8085afe..82891803 100644
--- a/gtksourceview/gtksourcegutterrenderertext.c
+++ b/gtksourceview/gtksourcegutterrenderertext.c
@@ -34,11 +34,11 @@
typedef struct
{
- gchar *text;
-
+ gchar *text;
PangoLayout *cached_layout;
-
- guint is_markup : 1;
+ GdkRGBA cached_color;
+ gsize text_len;
+ guint is_markup : 1;
} GtkSourceGutterRendererTextPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceGutterRendererText, gtk_source_gutter_renderer_text,
GTK_SOURCE_TYPE_GUTTER_RENDERER)
@@ -47,171 +47,89 @@ enum
{
PROP_0,
PROP_MARKUP,
- PROP_TEXT
+ PROP_TEXT,
+ N_PROPS
};
static void
-gutter_renderer_text_begin (GtkSourceGutterRenderer *renderer,
- cairo_t *cr,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end)
+gtk_source_gutter_renderer_text_begin (GtkSourceGutterRenderer *renderer,
+ GtkSourceGutterLines *lines)
{
+
GtkSourceGutterRendererText *text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private
(text);
- GtkTextView *view;
- view = gtk_source_gutter_renderer_get_view (renderer);
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->begin (renderer,
lines);
g_clear_object (&priv->cached_layout);
- priv->cached_layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
-
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->begin != NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->begin
(renderer,
- cr,
-
background_area,
-
cell_area,
- start,
- end);
- }
-}
-
-static void
-center_on (GtkTextView *view,
- GdkRectangle *cell_area,
- GtkTextIter *iter,
- gint width,
- gint height,
- gfloat xalign,
- gfloat yalign,
- gint *x,
- gint *y)
-{
- GdkRectangle location;
-
- 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;
+ priv->cached_layout = gtk_widget_create_pango_layout (GTK_WIDGET (renderer), NULL);
}
static void
-gutter_renderer_text_draw (GtkSourceGutterRenderer *renderer,
- cairo_t *cr,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GtkTextIter *start,
- GtkTextIter *end,
- GtkSourceGutterRendererState state)
+gtk_source_gutter_renderer_text_snapshot_line (GtkSourceGutterRenderer *renderer,
+ GtkSnapshot *snapshot,
+ GtkSourceGutterLines *lines,
+ guint line)
{
GtkSourceGutterRendererText *text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private
(text);
- GtkTextView *view;
+ PangoLayout *layout;
+ gfloat x;
+ gfloat y;
gint width;
gint height;
- gfloat xalign;
- gfloat yalign;
- GtkSourceGutterRendererAlignmentMode mode;
- gint x = 0;
- gint y = 0;
- GtkStyleContext *context;
-
- /* Chain up to draw background */
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->draw != NULL)
+
+ if (priv->text == NULL || priv->text_len == 0)
{
- GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->draw
(renderer,
- cr,
-
background_area,
-
cell_area,
- start,
- end,
- state);
+ return;
}
- view = gtk_source_gutter_renderer_get_view (renderer);
+ layout = priv->cached_layout;
if (priv->is_markup)
{
- pango_layout_set_markup (priv->cached_layout,
+ pango_layout_set_markup (layout,
priv->text,
- -1);
+ priv->text_len);
}
else
{
- pango_layout_set_text (priv->cached_layout,
+ pango_layout_set_text (layout,
priv->text,
- -1);
+ priv->text_len);
}
- pango_layout_get_pixel_size (priv->cached_layout, &width, &height);
+ pango_layout_get_pixel_size (layout, &width, &height);
- gtk_source_gutter_renderer_get_alignment (renderer,
- &xalign,
- &yalign);
+ gtk_source_gutter_renderer_align_cell (renderer,
+ line,
+ width,
+ height,
+ &x,
+ &y);
- /* Avoid calculations if we don't wrap text */
- if (gtk_text_view_get_wrap_mode (view) == GTK_WRAP_NONE)
- {
- mode = GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL;
- }
- else
- {
- mode = gtk_source_gutter_renderer_get_alignment_mode (renderer);
- }
+ gtk_snapshot_render_layout (snapshot,
+ gtk_widget_get_style_context (GTK_WIDGET (text)),
+ x,
+ y,
+ layout);
- switch (mode)
+ if (priv->is_markup)
{
- 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 (view,
- cell_area,
- start,
- width,
- height,
- xalign,
- yalign,
- &x,
- &y);
- break;
-
- case GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_LAST:
- center_on (view,
- cell_area,
- end,
- width,
- height,
- xalign,
- yalign,
- &x,
- &y);
- break;
-
- default:
- g_assert_not_reached ();
+ pango_layout_set_attributes (layout, NULL);
}
-
- context = gtk_widget_get_style_context (GTK_WIDGET (view));
- gtk_render_layout (context, cr, x, y, priv->cached_layout);
}
static void
-gutter_renderer_text_end (GtkSourceGutterRenderer *renderer)
+gtk_source_gutter_renderer_text_end (GtkSourceGutterRenderer *renderer)
{
+
GtkSourceGutterRendererText *text = GTK_SOURCE_GUTTER_RENDERER_TEXT (renderer);
GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private
(text);
- g_clear_object (&priv->cached_layout);
+ GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->end (renderer);
- if (GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->end != NULL)
- {
- GTK_SOURCE_GUTTER_RENDERER_CLASS (gtk_source_gutter_renderer_text_parent_class)->end
(renderer);
- }
+ g_clear_object (&priv->cached_layout);
}
static void
@@ -221,7 +139,7 @@ measure_text (GtkSourceGutterRendererText *renderer,
gint *width,
gint *height)
{
- GtkTextView *view;
+ GtkSourceView *view;
PangoLayout *layout;
view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (renderer));
@@ -290,13 +208,53 @@ gtk_source_gutter_renderer_text_measure_markup (GtkSourceGutterRendererText *ren
measure_text (renderer, markup, NULL, width, height);
}
+static void
+gtk_source_gutter_renderer_text_real_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkSourceGutterRendererText *renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (widget);
+ GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private
(renderer);
+
+ *minimum = 0;
+ *natural = 0;
+ *minimum_baseline = -1;
+ *natural_baseline = -1;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gint xpad = gtk_source_gutter_renderer_get_xpad (GTK_SOURCE_GUTTER_RENDERER (renderer));
+ gint width = 0;
+ gint height = 0;
+
+ if (priv->text != NULL)
+ {
+ if (priv->is_markup)
+ {
+ measure_text (renderer, priv->text, NULL, &width, &height);
+ }
+ else
+ {
+ measure_text (renderer, NULL, priv->text, &width, &height);
+ }
+ }
+
+ *natural = *minimum = width + 2 * xpad;
+ }
+
+}
+
static void
gtk_source_gutter_renderer_text_finalize (GObject *object)
{
GtkSourceGutterRendererText *renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
GtkSourceGutterRendererTextPrivate *priv = gtk_source_gutter_renderer_text_get_instance_private
(renderer);
- g_free (priv->text);
+ g_clear_pointer (&priv->text, g_free);
g_clear_object (&priv->cached_layout);
G_OBJECT_CLASS (gtk_source_gutter_renderer_text_parent_class)->finalize (object);
@@ -312,8 +270,18 @@ set_text (GtkSourceGutterRendererText *renderer,
g_free (priv->text);
- priv->text = length >= 0 ? g_strndup (text, length) : g_strdup (text);
- priv->is_markup = is_markup;
+ if (text == NULL)
+ {
+ priv->text_len = 0;
+ priv->text = NULL;
+ priv->is_markup = FALSE;
+ }
+ else
+ {
+ priv->text_len = length >= 0 ? length : strlen (text);
+ priv->text = g_strndup (text, priv->text_len);
+ priv->is_markup = !!is_markup;
+ }
}
static void
@@ -322,9 +290,7 @@ gtk_source_gutter_renderer_text_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- GtkSourceGutterRendererText *renderer;
-
- renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
+ GtkSourceGutterRendererText *renderer = GTK_SOURCE_GUTTER_RENDERER_TEXT (object);
switch (prop_id)
{
@@ -367,16 +333,18 @@ static void
gtk_source_gutter_renderer_text_class_init (GtkSourceGutterRendererTextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_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;
+ widget_class->measure = gtk_source_gutter_renderer_text_real_measure;
+
+ renderer_class->begin = gtk_source_gutter_renderer_text_begin;
+ renderer_class->end = gtk_source_gutter_renderer_text_end;
+ renderer_class->snapshot_line = gtk_source_gutter_renderer_text_snapshot_line;
g_object_class_install_property (object_class,
PROP_MARKUP,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]