mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-10-31 03:48:10 +00:00
Use GtkSourceGutter API to render diff line numbers
This commit is contained in:
parent
fadebf32d3
commit
19396f8fb0
5 changed files with 459 additions and 216 deletions
|
@ -24,6 +24,7 @@ NOINST_H_FILES = \
|
|||
gitg-commit-view.h \
|
||||
gitg-data-binding.h \
|
||||
gitg-debug.h \
|
||||
gitg-diff-line-renderer.h \
|
||||
gitg-diff-view.h \
|
||||
gitg-dirs.h \
|
||||
gitg-dnd.h \
|
||||
|
@ -58,6 +59,7 @@ gitg_SOURCES = \
|
|||
gitg-commit-view.c \
|
||||
gitg-data-binding.c \
|
||||
gitg-debug.c \
|
||||
gitg-diff-line-renderer.c \
|
||||
gitg-diff-view.c \
|
||||
gitg-dirs.c \
|
||||
gitg-dnd.c \
|
||||
|
|
255
gitg/gitg-diff-line-renderer.c
Normal file
255
gitg/gitg-diff-line-renderer.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
#include "gitg-diff-line-renderer.h"
|
||||
|
||||
#define GITG_DIFF_LINE_RENDERER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererPrivate))
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#endif
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_LINE_OLD,
|
||||
PROP_LINE_NEW
|
||||
};
|
||||
|
||||
struct _GitgDiffLineRendererPrivate
|
||||
{
|
||||
gint line_old;
|
||||
gint line_new;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GitgDiffLineRenderer, gitg_diff_line_renderer, GTK_TYPE_CELL_RENDERER)
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (gitg_diff_line_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LINE_OLD:
|
||||
self->priv->line_old = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_LINE_NEW:
|
||||
self->priv->line_new = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LINE_OLD:
|
||||
g_value_set_int (value, self->priv->line_old);
|
||||
break;
|
||||
case PROP_LINE_NEW:
|
||||
g_value_set_int (value, self->priv->line_new);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_render_impl (GtkCellRenderer *cell,
|
||||
GdkDrawable *window,
|
||||
GtkWidget *widget,
|
||||
GdkRectangle *background_area,
|
||||
GdkRectangle *cell_area,
|
||||
GdkRectangle *expose_area,
|
||||
GtkCellRendererState flags)
|
||||
{
|
||||
GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (cell);
|
||||
|
||||
/* Render new/old in the cell area */
|
||||
gchar old_str[16];
|
||||
gchar new_str[16];
|
||||
guint xpad;
|
||||
guint ypad;
|
||||
|
||||
PangoLayout *layout = gtk_widget_create_pango_layout (widget, "");
|
||||
pango_layout_set_width (layout, cell_area->width / 2);
|
||||
|
||||
pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
|
||||
|
||||
if (lr->priv->line_old >= 0)
|
||||
{
|
||||
g_snprintf (old_str, sizeof (old_str), "%d", lr->priv->line_old);
|
||||
}
|
||||
else
|
||||
{
|
||||
*old_str = '\0';
|
||||
}
|
||||
|
||||
if (lr->priv->line_new >= 0)
|
||||
{
|
||||
g_snprintf (new_str, sizeof (old_str), "%d", lr->priv->line_new);
|
||||
}
|
||||
else
|
||||
{
|
||||
*new_str = '\0';
|
||||
}
|
||||
|
||||
g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
|
||||
|
||||
pango_layout_set_text (layout, old_str, -1);
|
||||
gtk_paint_layout (widget->style,
|
||||
window,
|
||||
GTK_WIDGET_STATE (widget),
|
||||
FALSE,
|
||||
NULL,
|
||||
widget,
|
||||
NULL,
|
||||
cell_area->x + cell_area->width / 2 - 1 - xpad,
|
||||
cell_area->y,
|
||||
layout);
|
||||
|
||||
pango_layout_set_text (layout, new_str, -1);
|
||||
gtk_paint_layout (widget->style,
|
||||
window,
|
||||
GTK_WIDGET_STATE (widget),
|
||||
FALSE,
|
||||
NULL,
|
||||
widget,
|
||||
NULL,
|
||||
cell_area->x + cell_area->width - xpad,
|
||||
cell_area->y,
|
||||
layout);
|
||||
|
||||
g_object_unref (layout);
|
||||
|
||||
gtk_paint_vline (widget->style,
|
||||
window,
|
||||
GTK_WIDGET_STATE (widget),
|
||||
NULL,
|
||||
widget,
|
||||
NULL,
|
||||
background_area->y,
|
||||
background_area->y + background_area->height,
|
||||
background_area->x + background_area->width / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_get_size_impl (GtkCellRenderer *cell,
|
||||
GtkWidget *widget,
|
||||
GdkRectangle *cell_area,
|
||||
gint *x_offset,
|
||||
gint *y_offset,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (cell);
|
||||
|
||||
/* Get size of this rendering */
|
||||
PangoLayout *layout;
|
||||
gchar str[16];
|
||||
gint pixel_width;
|
||||
gint pixel_height;
|
||||
guint xpad;
|
||||
guint ypad;
|
||||
|
||||
g_snprintf(str, sizeof(str), "%d", MAX(MAX(99, lr->priv->line_old), lr->priv->line_new));
|
||||
layout = gtk_widget_create_pango_layout (widget, str);
|
||||
pango_layout_get_pixel_size(layout, &pixel_width, &pixel_height);
|
||||
|
||||
g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
|
||||
|
||||
pixel_width = pixel_width * 2 + xpad * 4 + 3;
|
||||
pixel_height += ypad * 2;
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = pixel_width;
|
||||
}
|
||||
|
||||
if (height)
|
||||
{
|
||||
*height = pixel_height;
|
||||
}
|
||||
|
||||
if (x_offset)
|
||||
{
|
||||
*x_offset = 0;
|
||||
}
|
||||
|
||||
if (y_offset)
|
||||
{
|
||||
*y_offset = 0;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (layout));
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_class_init (GitgDiffLineRendererClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkCellRendererClass *cell_renderer_class = GTK_CELL_RENDERER_CLASS (klass);
|
||||
|
||||
cell_renderer_class->render = gitg_diff_line_renderer_render_impl;
|
||||
cell_renderer_class->get_size = gitg_diff_line_renderer_get_size_impl;
|
||||
|
||||
object_class->finalize = gitg_diff_line_renderer_finalize;
|
||||
object_class->set_property = gitg_diff_line_renderer_set_property;
|
||||
object_class->get_property = gitg_diff_line_renderer_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LINE_OLD,
|
||||
g_param_spec_int ("line-old",
|
||||
"Line Old",
|
||||
"Line Old",
|
||||
-1,
|
||||
G_MAXINT,
|
||||
-1,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LINE_NEW,
|
||||
g_param_spec_int ("line-new",
|
||||
"Line New",
|
||||
"Line New",
|
||||
-1,
|
||||
G_MAXINT,
|
||||
-1,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_type_class_add_private (object_class, sizeof(GitgDiffLineRendererPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_line_renderer_init (GitgDiffLineRenderer *self)
|
||||
{
|
||||
self->priv = GITG_DIFF_LINE_RENDERER_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
GitgDiffLineRenderer *
|
||||
gitg_diff_line_renderer_new ()
|
||||
{
|
||||
return g_object_new (GITG_TYPE_DIFF_LINE_RENDERER, NULL);
|
||||
}
|
36
gitg/gitg-diff-line-renderer.h
Normal file
36
gitg/gitg-diff-line-renderer.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef __GITG_DIFF_LINE_RENDERER_H__
|
||||
#define __GITG_DIFF_LINE_RENDERER_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GITG_TYPE_DIFF_LINE_RENDERER (gitg_diff_line_renderer_get_type ())
|
||||
#define GITG_DIFF_LINE_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRenderer))
|
||||
#define GITG_DIFF_LINE_RENDERER_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRenderer const))
|
||||
#define GITG_DIFF_LINE_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererClass))
|
||||
#define GITG_IS_DIFF_LINE_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_DIFF_LINE_RENDERER))
|
||||
#define GITG_IS_DIFF_LINE_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_DIFF_LINE_RENDERER))
|
||||
#define GITG_DIFF_LINE_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererClass))
|
||||
|
||||
typedef struct _GitgDiffLineRenderer GitgDiffLineRenderer;
|
||||
typedef struct _GitgDiffLineRendererClass GitgDiffLineRendererClass;
|
||||
typedef struct _GitgDiffLineRendererPrivate GitgDiffLineRendererPrivate;
|
||||
|
||||
struct _GitgDiffLineRenderer {
|
||||
GtkCellRenderer parent;
|
||||
|
||||
GitgDiffLineRendererPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GitgDiffLineRendererClass {
|
||||
GtkCellRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType gitg_diff_line_renderer_get_type (void) G_GNUC_CONST;
|
||||
GitgDiffLineRenderer *gitg_diff_line_renderer_new (void);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GITG_DIFF_LINE_RENDERER_H__ */
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "gitg-diff-view.h"
|
||||
#include "gitg-types.h"
|
||||
#include "gitg-diff-line-renderer.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -40,6 +42,17 @@
|
|||
static void on_buffer_insert_text(GtkTextBuffer *buffer, GtkTextIter *iter, gchar const *text, gint len, GitgDiffView *view);
|
||||
static void on_buffer_delete_range(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GitgDiffView *view);
|
||||
|
||||
static void
|
||||
line_renderer_size_func (GtkSourceGutter *gutter,
|
||||
GtkCellRenderer *cell,
|
||||
GitgDiffView *view);
|
||||
static void
|
||||
line_renderer_data_func (GtkSourceGutter *gutter,
|
||||
GtkCellRenderer *cell,
|
||||
gint line_number,
|
||||
gboolean current_line,
|
||||
GitgDiffView *view);
|
||||
|
||||
static gboolean on_idle_scan(GitgDiffView *view);
|
||||
|
||||
/* Signals */
|
||||
|
@ -98,6 +111,12 @@ struct _GitgDiffViewPrivate
|
|||
gboolean diff_enabled;
|
||||
GtkTextBuffer *current_buffer;
|
||||
GtkTextTag *invisible_tag;
|
||||
|
||||
GitgDiffLineRenderer *line_renderer;
|
||||
|
||||
Region *lines_current_region;
|
||||
gint lines_previous_line;
|
||||
guint lines_counters[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(GitgDiffView, gitg_diff_view, GTK_TYPE_SOURCE_VIEW)
|
||||
|
@ -151,14 +170,14 @@ regions_free(GitgDiffView *view, gboolean remove_signals)
|
|||
}
|
||||
|
||||
static void
|
||||
gitg_diff_view_finalize(GObject *object)
|
||||
gitg_diff_view_finalize (GObject *object)
|
||||
{
|
||||
GitgDiffView *view = GITG_DIFF_VIEW(object);
|
||||
GitgDiffView *view = GITG_DIFF_VIEW (object);
|
||||
|
||||
regions_free(view, TRUE);
|
||||
g_sequence_free(view->priv->regions_index);
|
||||
regions_free (view, TRUE);
|
||||
g_sequence_free (view->priv->regions_index);
|
||||
|
||||
G_OBJECT_CLASS(gitg_diff_view_parent_class)->finalize(object);
|
||||
G_OBJECT_CLASS (gitg_diff_view_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -200,6 +219,12 @@ gitg_diff_view_get_property(GObject *object, guint prop_id, GValue *value, GPara
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_view_constructed (GObject *object)
|
||||
{
|
||||
g_object_set (object, "show-line-numbers", FALSE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gitg_diff_view_class_init(GitgDiffViewClass *klass)
|
||||
{
|
||||
|
@ -210,6 +235,8 @@ gitg_diff_view_class_init(GitgDiffViewClass *klass)
|
|||
object_class->set_property = gitg_diff_view_set_property;
|
||||
object_class->get_property = gitg_diff_view_get_property;
|
||||
|
||||
object_class->constructed = gitg_diff_view_constructed;
|
||||
|
||||
widget_class->expose_event = gitg_diff_view_expose;
|
||||
|
||||
diff_view_signals[HEADER_ADDED] =
|
||||
|
@ -259,88 +286,42 @@ on_buffer_set(GitgDiffView *self, GParamSpec *spec, gpointer userdata)
|
|||
}
|
||||
|
||||
static void
|
||||
gitg_diff_view_init(GitgDiffView *self)
|
||||
gitg_diff_view_init (GitgDiffView *self)
|
||||
{
|
||||
self->priv = GITG_DIFF_VIEW_GET_PRIVATE(self);
|
||||
GtkSourceGutter *gutter;
|
||||
|
||||
self->priv->regions_index = g_sequence_new(NULL);
|
||||
self->priv = GITG_DIFF_VIEW_GET_PRIVATE (self);
|
||||
|
||||
g_signal_connect(self, "notify::buffer", G_CALLBACK(on_buffer_set), NULL);
|
||||
self->priv->regions_index = g_sequence_new (NULL);
|
||||
self->priv->line_renderer = gitg_diff_line_renderer_new ();
|
||||
|
||||
g_object_set (self->priv->line_renderer, "xpad", 2, NULL);
|
||||
|
||||
gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
|
||||
|
||||
gtk_source_gutter_insert (gutter,
|
||||
GTK_CELL_RENDERER (self->priv->line_renderer),
|
||||
0);
|
||||
|
||||
gtk_source_gutter_set_cell_data_func (gutter,
|
||||
GTK_CELL_RENDERER (self->priv->line_renderer),
|
||||
(GtkSourceGutterDataFunc)line_renderer_data_func,
|
||||
self,
|
||||
NULL);
|
||||
|
||||
gtk_source_gutter_set_cell_size_func (gutter,
|
||||
GTK_CELL_RENDERER (self->priv->line_renderer),
|
||||
(GtkSourceGutterSizeFunc)line_renderer_size_func,
|
||||
self,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (self, "notify::buffer", G_CALLBACK (on_buffer_set), NULL);
|
||||
}
|
||||
|
||||
GitgDiffView*
|
||||
gitg_diff_view_new()
|
||||
GitgDiffView *
|
||||
gitg_diff_view_new ()
|
||||
{
|
||||
return g_object_new(GITG_TYPE_DIFF_VIEW, NULL);
|
||||
}
|
||||
|
||||
/* This function is taken from gtk+/tests/testtext.c */
|
||||
static void
|
||||
get_lines (GtkTextView *text_view, gint first_y, gint last_y, GArray *buffer_coords, GArray *line_heights, GArray *numbers, gint *countp)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
gint count;
|
||||
gint size;
|
||||
gint last_line_num = -1;
|
||||
|
||||
g_array_set_size(buffer_coords, 0);
|
||||
g_array_set_size(numbers, 0);
|
||||
|
||||
if (line_heights != NULL)
|
||||
g_array_set_size(line_heights, 0);
|
||||
|
||||
/* Get iter at first y */
|
||||
gtk_text_view_get_line_at_y(text_view, &iter, first_y, NULL);
|
||||
|
||||
/* For each iter, get its location and add it to the arrays.
|
||||
* Stop when we pass last_y */
|
||||
count = 0;
|
||||
size = 0;
|
||||
|
||||
while (!gtk_text_iter_is_end(&iter))
|
||||
{
|
||||
gint y, height;
|
||||
|
||||
gtk_text_view_get_line_yrange(text_view, &iter, &y, &height);
|
||||
|
||||
g_array_append_val(buffer_coords, y);
|
||||
|
||||
if (line_heights)
|
||||
g_array_append_val(line_heights, height);
|
||||
|
||||
last_line_num = gtk_text_iter_get_line(&iter);
|
||||
g_array_append_val(numbers, last_line_num);
|
||||
|
||||
++count;
|
||||
|
||||
if ((y + height) >= last_y)
|
||||
break;
|
||||
|
||||
gtk_text_iter_forward_line(&iter);
|
||||
}
|
||||
|
||||
if (gtk_text_iter_is_end(&iter))
|
||||
{
|
||||
gint y, 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(buffer_coords, y);
|
||||
|
||||
if (line_heights)
|
||||
g_array_append_val(line_heights, height);
|
||||
|
||||
g_array_append_val(numbers, line_num);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
*countp = count;
|
||||
return g_object_new (GITG_TYPE_DIFF_VIEW, NULL);
|
||||
}
|
||||
|
||||
static gint
|
||||
|
@ -353,13 +334,17 @@ index_compare(gconstpointer a, gconstpointer b, gpointer userdata)
|
|||
}
|
||||
|
||||
static void
|
||||
ensure_max_line(GitgDiffView *view, Hunk *hunk)
|
||||
ensure_max_line (GitgDiffView *view, Hunk *hunk)
|
||||
{
|
||||
guint num = hunk->region.next ? hunk->region.next->line - hunk->region.line : 0;
|
||||
guint m = MAX(hunk->new + num, hunk->old + num);
|
||||
guint m = MAX (hunk->new + num, hunk->old + num);
|
||||
|
||||
if (m > view->priv->max_line_count)
|
||||
{
|
||||
view->priv->max_line_count = m;
|
||||
|
||||
gtk_source_gutter_queue_draw (gtk_source_view_get_gutter (GTK_SOURCE_VIEW (view), GTK_TEXT_WINDOW_LEFT));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -371,7 +356,9 @@ add_region(GitgDiffView *view, Region *region)
|
|||
region->prev = view->priv->last_region;
|
||||
|
||||
if (view->priv->last_region->type == GITG_DIFF_ITER_TYPE_HUNK)
|
||||
{
|
||||
ensure_max_line(view, (Hunk *)view->priv->last_region);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -387,9 +374,13 @@ add_region(GitgDiffView *view, Region *region)
|
|||
iter.userdata2 = region;
|
||||
|
||||
if (region->type == GITG_DIFF_ITER_TYPE_HEADER)
|
||||
{
|
||||
g_signal_emit(view, diff_view_signals[HEADER_ADDED], 0, &iter);
|
||||
}
|
||||
else if (region->type == GITG_DIFF_ITER_TYPE_HUNK)
|
||||
{
|
||||
g_signal_emit(view, diff_view_signals[HUNK_ADDED], 0, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -407,7 +398,9 @@ parse_hunk_info(Hunk *hunk, GtkTextIter *iter)
|
|||
gchar *new = g_utf8_strchr(text, -1, '+');
|
||||
|
||||
if (!old || !new)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hunk->old = atoi(old + 1);
|
||||
hunk->new = atoi(new + 1);
|
||||
|
@ -429,12 +422,16 @@ ensure_scan(GitgDiffView *view, guint last_line)
|
|||
GtkTextIter end = iter;
|
||||
|
||||
if (!gtk_text_iter_forward_line(&iter))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++view->priv->last_scan_line;
|
||||
|
||||
if (!gtk_text_iter_forward_chars(&end, 3))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gchar *text = gtk_text_iter_get_text(&start, &end);
|
||||
|
||||
|
@ -457,7 +454,9 @@ ensure_scan(GitgDiffView *view, guint last_line)
|
|||
g_free(text);
|
||||
|
||||
if (!gtk_text_iter_forward_chars(&end, 7))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
text = gtk_text_iter_get_text(&start, &end);
|
||||
|
||||
|
@ -479,7 +478,9 @@ ensure_scan(GitgDiffView *view, guint last_line)
|
|||
}
|
||||
|
||||
if (view->priv->last_region && view->priv->last_region->type == GITG_DIFF_ITER_TYPE_HUNK)
|
||||
{
|
||||
ensure_max_line(view, (Hunk *)view->priv->last_region);
|
||||
}
|
||||
}
|
||||
|
||||
static Region *
|
||||
|
@ -491,14 +492,18 @@ find_current_region(GitgDiffView *view, guint line)
|
|||
iter = g_sequence_search(view->priv->regions_index, &tmp, index_compare, NULL);
|
||||
|
||||
if (!iter || g_sequence_iter_is_begin(iter))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_sequence_iter_is_end(iter))
|
||||
{
|
||||
Region *ret = (Region *)g_sequence_get(iter);
|
||||
|
||||
if (ret->line == line)
|
||||
{
|
||||
return ret->visible ? ret : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Region *ret = (Region *)g_sequence_get(g_sequence_iter_prev(iter));
|
||||
|
@ -513,8 +518,11 @@ line_has_prefix(GitgDiffView *view, guint line, gchar const *prefix)
|
|||
gtk_text_buffer_get_iter_at_line(view->priv->current_buffer, &iter, line);
|
||||
|
||||
GtkTextIter end = iter;
|
||||
|
||||
if (!gtk_text_iter_forward_chars(&end, g_utf8_strlen(prefix, -1)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar *text = gtk_text_iter_get_text(&iter, &end);
|
||||
gboolean ret = g_str_has_prefix(text, prefix);
|
||||
|
@ -553,146 +561,88 @@ get_initial_counters(GitgDiffView *view, Region *region, guint line, guint count
|
|||
}
|
||||
|
||||
static void
|
||||
paint_line_numbers(GitgDiffView *view, GdkEventExpose *event)
|
||||
line_renderer_size_func (GtkSourceGutter *gutter,
|
||||
GtkCellRenderer *cell,
|
||||
GitgDiffView *view)
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
GdkWindow *win;
|
||||
PangoLayout *layout;
|
||||
GArray *numbers;
|
||||
GArray *pixels;
|
||||
gchar str_old[16]; /* we don't expect more than ten million lines ;-) */
|
||||
gchar str_new[16];
|
||||
gint y1, y2;
|
||||
gint count;
|
||||
gint margin_width;
|
||||
gint text_width;
|
||||
gint i;
|
||||
GtkTextIter cur;
|
||||
|
||||
text_view = GTK_TEXT_VIEW(view);
|
||||
win = gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_LEFT);
|
||||
|
||||
y1 = event->area.y;
|
||||
y2 = y1 + event->area.height;
|
||||
|
||||
/* get the extents of the line printing */
|
||||
gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, y1, NULL, &y1);
|
||||
gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, y2, NULL, &y2);
|
||||
|
||||
numbers = g_array_new(FALSE, FALSE, sizeof(gint));
|
||||
pixels = g_array_new(FALSE, FALSE, sizeof(gint));
|
||||
|
||||
/* get the line numbers and y coordinates. */
|
||||
get_lines(text_view, y1, y2, pixels, NULL, numbers, &count);
|
||||
|
||||
/* A zero-lined document should display a "1"; we don't need to worry about
|
||||
scrolling effects of the text widget in this special case */
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
gint y = 0;
|
||||
gint n = 0;
|
||||
count = 1;
|
||||
g_array_append_val(pixels, y);
|
||||
g_array_append_val(numbers, n);
|
||||
}
|
||||
|
||||
/* Ensure scanned until last needed line */
|
||||
guint last = g_array_index(numbers, gint, count - 1);
|
||||
ensure_scan(view, last);
|
||||
|
||||
/* set size */
|
||||
g_snprintf(str_old, sizeof(str_old), "%d", MAX(99, view->priv->max_line_count));
|
||||
layout = gtk_widget_create_pango_layout(GTK_WIDGET(view), str_old);
|
||||
|
||||
pango_layout_get_pixel_size(layout, &text_width, NULL);
|
||||
|
||||
/* determine the width of the left margin. */
|
||||
margin_width = text_width * 2 + 9;
|
||||
|
||||
guint extra_width = 0;
|
||||
|
||||
if (gtk_source_view_get_show_line_marks(GTK_SOURCE_VIEW(view)))
|
||||
extra_width = 20;
|
||||
|
||||
pango_layout_set_width(layout, text_width);
|
||||
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
|
||||
|
||||
gtk_text_view_set_border_window_size(GTK_TEXT_VIEW(text_view), GTK_TEXT_WINDOW_LEFT, margin_width + extra_width);
|
||||
gtk_text_buffer_get_iter_at_mark(text_view->buffer, &cur, gtk_text_buffer_get_insert(text_view->buffer));
|
||||
|
||||
Region *current = NULL;
|
||||
guint counters[2];
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
gint pos;
|
||||
gint line_to_paint;
|
||||
|
||||
gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, g_array_index(pixels, gint, i), NULL, &pos);
|
||||
line_to_paint = g_array_index(numbers, gint, i);
|
||||
|
||||
if (!current)
|
||||
{
|
||||
current = find_current_region(view, line_to_paint);
|
||||
|
||||
if (current)
|
||||
get_initial_counters(view, current, line_to_paint, counters);
|
||||
}
|
||||
|
||||
*str_old = '\0';
|
||||
*str_new = '\0';
|
||||
|
||||
if (current && current->type == GITG_DIFF_ITER_TYPE_HUNK && line_to_paint != current->line)
|
||||
{
|
||||
Hunk *hunk = (Hunk *)current;
|
||||
|
||||
if (draw_old(view, line_to_paint))
|
||||
g_snprintf(str_old, sizeof(str_old), "%d", hunk->old + counters[0]++);
|
||||
|
||||
if (draw_new(view, line_to_paint))
|
||||
g_snprintf(str_new, sizeof(str_new), "%d", hunk->new + counters[1]++);
|
||||
}
|
||||
|
||||
pango_layout_set_markup(layout, str_old, -1);
|
||||
gtk_paint_layout(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), FALSE, NULL, GTK_WIDGET(view), NULL, margin_width - 7 - text_width, pos, layout);
|
||||
|
||||
pango_layout_set_markup(layout, str_new, -1);
|
||||
gtk_paint_layout(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), FALSE, NULL, GTK_WIDGET(view), NULL, margin_width - 2, pos, layout);
|
||||
|
||||
if (current && current->next && line_to_paint == current->next->line - 1)
|
||||
{
|
||||
counters[0] = counters[1] = 0;
|
||||
current = current->next->visible ? current->next : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_paint_vline(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), NULL, GTK_WIDGET(view), NULL, event->area.y, event->area.y + event->area.height, 4 + text_width);
|
||||
|
||||
g_array_free(pixels, TRUE);
|
||||
g_array_free(numbers, TRUE);
|
||||
|
||||
g_object_unref(G_OBJECT(layout));
|
||||
g_object_set (cell,
|
||||
"line_old", view->priv->max_line_count,
|
||||
"line_new", view->priv->max_line_count,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gint
|
||||
gitg_diff_view_expose(GtkWidget *widget, GdkEventExpose *event)
|
||||
static void
|
||||
line_renderer_data_func (GtkSourceGutter *gutter,
|
||||
GtkCellRenderer *cell,
|
||||
gint line_number,
|
||||
gboolean current_line,
|
||||
GitgDiffView *view)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GtkTextView *text_view = GTK_TEXT_VIEW(widget);
|
||||
GitgDiffView *view = GITG_DIFF_VIEW(widget);
|
||||
gint line_old = -1;
|
||||
gint line_new = -1;
|
||||
Region **current = &view->priv->lines_current_region;
|
||||
|
||||
if (event->window == gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_LEFT) &&
|
||||
view->priv->diff_enabled && gtk_source_view_get_show_line_numbers(GTK_SOURCE_VIEW(view)))
|
||||
ensure_scan (view, line_number);
|
||||
|
||||
if (!*current)
|
||||
{
|
||||
paint_line_numbers(GITG_DIFF_VIEW(widget), event);
|
||||
ret = TRUE;
|
||||
*current = find_current_region (view, line_number);
|
||||
|
||||
if (*current)
|
||||
{
|
||||
get_initial_counters (view,
|
||||
*current,
|
||||
line_number,
|
||||
view->priv->lines_counters);
|
||||
}
|
||||
}
|
||||
|
||||
if (GTK_WIDGET_CLASS(gitg_diff_view_parent_class)->expose_event)
|
||||
ret = ret || GTK_WIDGET_CLASS(gitg_diff_view_parent_class)->expose_event(widget, event);
|
||||
if (*current &&
|
||||
(*current)->type == GITG_DIFF_ITER_TYPE_HUNK &&
|
||||
line_number != (*current)->line)
|
||||
{
|
||||
Hunk *hunk = (Hunk *)*current;
|
||||
|
||||
return ret;
|
||||
if (draw_old (view, line_number))
|
||||
{
|
||||
line_old = hunk->old + view->priv->lines_counters[0]++;
|
||||
}
|
||||
|
||||
if (draw_new (view, line_number))
|
||||
{
|
||||
line_new = hunk->new + view->priv->lines_counters[1]++;
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set (cell, "line_old", line_old, "line_new", line_new, NULL);
|
||||
|
||||
if (*current && (*current)->next && line_number == (*current)->next->line - 1)
|
||||
{
|
||||
view->priv->lines_counters[0] = view->priv->lines_counters[1] = 0;
|
||||
*current = (*current)->next->visible ? (*current)->next : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
gitg_diff_view_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event)
|
||||
{
|
||||
GitgDiffView *view = GITG_DIFF_VIEW (widget);
|
||||
|
||||
/* Prepare for new round of expose on the line renderer */
|
||||
view->priv->lines_current_region = NULL;
|
||||
view->priv->lines_previous_line = -1;
|
||||
view->priv->lines_counters[0] = 0;
|
||||
view->priv->lines_counters[1] = 0;
|
||||
|
||||
if (GTK_WIDGET_CLASS (gitg_diff_view_parent_class)->expose_event)
|
||||
{
|
||||
return GTK_WIDGET_CLASS (gitg_diff_view_parent_class)->expose_event (widget, event);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -374,7 +374,7 @@
|
|||
<object class="GitgDiffView" id="revision_diff">
|
||||
<property name="editable">False</property>
|
||||
<property name="cursor_visible">False</property>
|
||||
<property name="show_line_numbers">True</property>
|
||||
<property name="show_line_numbers">False</property>
|
||||
<property name="tab_width">4</property>
|
||||
</object>
|
||||
</child>
|
||||
|
@ -574,7 +574,7 @@
|
|||
<property name="left_margin">2</property>
|
||||
<property name="right_margin">2</property>
|
||||
<property name="cursor_visible">False</property>
|
||||
<property name="show_line_numbers">True</property>
|
||||
<property name="show_line_numbers">False</property>
|
||||
<property name="tab_width">4</property>
|
||||
</object>
|
||||
</child>
|
||||
|
|
Loading…
Reference in a new issue