[anjuta] libanjuta: Add AnjutaCellRendererDiff



commit dae9d988b851c172c706ffe7f4afd27b3c9ebff5
Author: James Liggett <jrliggett cox net>
Date:   Wed Aug 14 16:08:24 2013 -0700

    libanjuta: Add AnjutaCellRendererDiff
    
    This custom cell renderer highlights unified diffs with the cgit color scheme
    (i.e. adds are green, removes are red, and hunks are blue.)

 libanjuta/Makefile.am                       |    4 +-
 libanjuta/anjuta-cell-renderer-diff.c       |  234 +++++++++++++++++++++++++++
 libanjuta/anjuta-cell-renderer-diff.h       |   61 +++++++
 libanjuta/tests/Makefile.am                 |    7 +-
 libanjuta/tests/anjuta-diff-renderer-test.c |  124 ++++++++++++++
 5 files changed, 428 insertions(+), 2 deletions(-)
---
diff --git a/libanjuta/Makefile.am b/libanjuta/Makefile.am
index 4ac227e..d47c978 100644
--- a/libanjuta/Makefile.am
+++ b/libanjuta/Makefile.am
@@ -138,7 +138,9 @@ libanjuta_3_la_SOURCES= \
        anjuta-close-button.c \
        anjuta-close-button.h \
        anjuta-modeline.c \
-       anjuta-modeline.h
+       anjuta-modeline.h \
+       anjuta-cell-renderer-diff.c \
+       anjuta-cell-renderer-diff.h
 
 # Glade module
 if ENABLE_GLADE_CATALOG
diff --git a/libanjuta/anjuta-cell-renderer-diff.c b/libanjuta/anjuta-cell-renderer-diff.c
new file mode 100644
index 0000000..e52729b
--- /dev/null
+++ b/libanjuta/anjuta-cell-renderer-diff.c
@@ -0,0 +1,234 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
+/*
+ * anjuta-cell-renderer-diff.c
+ * Copyright (C) 2013 James Liggett <jrliggett cox net>
+ *
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "anjuta-cell-renderer-diff.h"
+
+struct _AnjutaCellRendererDiffPrivate
+{
+       GtkCellRenderer *text_cell;
+};
+
+
+enum
+{
+       PROP_0,
+
+       PROP_DIFF
+};
+
+
+
+G_DEFINE_TYPE (AnjutaCellRendererDiff, anjuta_cell_renderer_diff, GTK_TYPE_CELL_RENDERER);
+
+static void
+anjuta_cell_renderer_diff_init (AnjutaCellRendererDiff *self)
+{
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ANJUTA_TYPE_CELL_RENDERER_DIFF, 
+                                                 AnjutaCellRendererDiffPrivate);
+
+       self->priv->text_cell = gtk_cell_renderer_text_new ();
+}
+
+static void
+anjuta_cell_renderer_diff_finalize (GObject *object)
+{
+       AnjutaCellRendererDiff *self;
+
+       self = ANJUTA_CELL_RENDERER_DIFF (object);
+
+       g_object_unref (self->priv->text_cell);
+
+       G_OBJECT_CLASS (anjuta_cell_renderer_diff_parent_class)->finalize (object);
+}
+
+static void
+anjuta_cell_renderer_diff_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec 
*pspec)
+{
+       g_return_if_fail (ANJUTA_IS_CELL_RENDERER_DIFF (object));
+
+       switch (prop_id)
+       {
+       case PROP_DIFF:
+               anjuta_cell_renderer_diff_set_diff (ANJUTA_CELL_RENDERER_DIFF (object),
+                                                   g_value_get_string (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+anjuta_cell_renderer_diff_render (GtkCellRenderer *cell,
+                                  cairo_t *cr,
+                                  GtkWidget *widget,
+                                  const GdkRectangle *background_area,
+                                  const GdkRectangle *cell_area,
+                                  GtkCellRendererState flags)
+{
+       AnjutaCellRendererDiff *self;
+
+       self = ANJUTA_CELL_RENDERER_DIFF (cell);
+
+       gtk_cell_renderer_render (self->priv->text_cell, cr, widget, 
+                                 background_area, cell_area, flags);
+}
+
+static void
+anjuta_cell_renderer_diff_get_preferred_width (GtkCellRenderer *cell,
+                                               GtkWidget *widget,
+                                               gint *minimum,
+                                               gint *natural)
+{
+       AnjutaCellRendererDiff *self;
+
+       self = ANJUTA_CELL_RENDERER_DIFF (cell);
+
+       gtk_cell_renderer_get_preferred_width (self->priv->text_cell, widget, 
+                                              minimum, natural);
+}
+
+static void
+anjuta_cell_renderer_diff_get_preferred_height (GtkCellRenderer *cell,
+                                                GtkWidget *widget,
+                                                gint *minimum,
+                                                gint *natural)
+{
+       AnjutaCellRendererDiff *self;
+
+       self = ANJUTA_CELL_RENDERER_DIFF (cell);
+
+       gtk_cell_renderer_get_preferred_height (self->priv->text_cell, widget, 
+                                               minimum, natural);
+}
+
+static void
+anjuta_cell_renderer_diff_class_init (AnjutaCellRendererDiffClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkCellRendererClass *parent_class = GTK_CELL_RENDERER_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (AnjutaCellRendererDiffPrivate));
+
+       object_class->finalize = anjuta_cell_renderer_diff_finalize;
+       object_class->set_property = anjuta_cell_renderer_diff_set_property;
+       parent_class->render = anjuta_cell_renderer_diff_render;
+       parent_class->get_preferred_width = anjuta_cell_renderer_diff_get_preferred_width;;
+       parent_class->get_preferred_height = anjuta_cell_renderer_diff_get_preferred_height;
+
+       g_object_class_install_property (object_class,
+                                        PROP_DIFF,
+                                        g_param_spec_string ("diff",
+                                                             "diff",
+                                                             "Diff to render",
+                                                             "",
+                                                             G_PARAM_WRITABLE));
+}
+
+
+static PangoAttrList *
+create_attribute_list (const gchar *diff)
+{
+       PangoAttrList *list;
+       const gchar *line_begin, *line_end;
+       guint begin_index, end_index;
+       gboolean found_hunk = FALSE;
+       PangoAttribute *attribute;
+
+       list = pango_attr_list_new ();
+
+       /* Make all of the text monospace */
+       pango_attr_list_insert (list, pango_attr_family_new ("Monospace"));
+
+       line_begin = diff;
+
+       while (line_begin && *line_begin)
+       {
+               line_end = strchr (line_begin, '\n');
+
+               if (!line_end)
+                       line_end = diff + strlen (line_begin);
+
+               begin_index = line_begin - diff;
+               end_index = line_end - diff;
+               attribute = NULL;
+
+               if (line_begin[0] == '@' && line_begin[1] == '@')
+               {
+                       /* Dark blue */
+                       attribute = pango_attr_foreground_new (0, 0, 0x8000);
+
+                       /* Don't decorate diff headers */
+                       found_hunk = TRUE;
+               }
+               else if (found_hunk)
+               {
+                       if (line_begin[0] == '+')
+                       {
+                               /* Dark green */
+                               attribute = pango_attr_foreground_new (0, 0x8000, 0);
+                       }
+                       else if (line_begin[0] == '-')
+                       {
+                               /* Red */
+                               attribute = pango_attr_foreground_new (0xffff, 0, 0);   
+                       }
+               }
+                       
+               if (attribute)
+               {
+                       attribute->start_index = begin_index;
+                       attribute->end_index = end_index;
+
+                       pango_attr_list_insert (list, attribute);
+               }
+
+               if (*line_end)
+                       line_begin = line_end + 1;
+               else
+                       line_begin = NULL;
+
+       }
+
+       return list;
+}
+
+void
+anjuta_cell_renderer_diff_set_diff (AnjutaCellRendererDiff *self, 
+                                    const gchar *diff)
+{
+       PangoAttrList *attributes = NULL;
+
+       if (diff)
+               attributes = create_attribute_list (diff);
+
+       g_object_set (G_OBJECT (self->priv->text_cell),
+                     "attributes", attributes, 
+                     "text", diff, 
+                     NULL);
+
+       pango_attr_list_unref (attributes);
+}
+
+GtkCellRenderer *
+anjuta_cell_renderer_diff_new (void)
+{
+       return g_object_new (ANJUTA_TYPE_CELL_RENDERER_DIFF, NULL);
+}
+
diff --git a/libanjuta/anjuta-cell-renderer-diff.h b/libanjuta/anjuta-cell-renderer-diff.h
new file mode 100644
index 0000000..345f1f7
--- /dev/null
+++ b/libanjuta/anjuta-cell-renderer-diff.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
+/*
+ * anjuta-cell-renderer-diff.h
+ * Copyright (C) 2013 James Liggett <jrliggett cox net>
+ *
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ANJUTA_CELL_RENDERER_DIFF_H_
+#define _ANJUTA_CELL_RENDERER_DIFF_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+#define ANJUTA_TYPE_CELL_RENDERER_DIFF             (anjuta_cell_renderer_diff_get_type ())
+#define ANJUTA_CELL_RENDERER_DIFF(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
ANJUTA_TYPE_CELL_RENDERER_DIFF, AnjutaCellRendererDiff))
+#define ANJUTA_CELL_RENDERER_DIFF_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
ANJUTA_TYPE_CELL_RENDERER_DIFF, AnjutaCellRendererDiffClass))
+#define ANJUTA_IS_CELL_RENDERER_DIFF(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
ANJUTA_TYPE_CELL_RENDERER_DIFF))
+#define ANJUTA_IS_CELL_RENDERER_DIFF_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
ANJUTA_TYPE_CELL_RENDERER_DIFF))
+#define ANJUTA_CELL_RENDERER_DIFF_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
ANJUTA_TYPE_CELL_RENDERER_DIFF, AnjutaCellRendererDiffClass))
+
+typedef struct _AnjutaCellRendererDiffClass AnjutaCellRendererDiffClass;
+typedef struct _AnjutaCellRendererDiff AnjutaCellRendererDiff;
+typedef struct _AnjutaCellRendererDiffPrivate AnjutaCellRendererDiffPrivate;
+
+
+struct _AnjutaCellRendererDiffClass
+{
+       GtkCellRendererClass parent_class;
+};
+
+struct _AnjutaCellRendererDiff
+{
+       GtkCellRenderer parent_instance;
+
+       AnjutaCellRendererDiffPrivate *priv;
+};
+
+GType anjuta_cell_renderer_diff_get_type (void) G_GNUC_CONST;
+void anjuta_cell_renderer_diff_set_diff (AnjutaCellRendererDiff *self, 
+                                         const gchar *diff);
+GtkCellRenderer *anjuta_cell_renderer_diff_new (void);
+
+G_END_DECLS
+
+#endif /* _ANJUTA_CELL_RENDERER_DIFF_H_ */
+
diff --git a/libanjuta/tests/Makefile.am b/libanjuta/tests/Makefile.am
index 72d8dde..676b1d6 100644
--- a/libanjuta/tests/Makefile.am
+++ b/libanjuta/tests/Makefile.am
@@ -1,7 +1,8 @@
 noinst_PROGRAMS = \
                anjuta-completion-test \
                anjuta-tabber-test \
-               anjuta-token-test
+               anjuta-token-test \
+               anjuta-diff-renderer-test
 
 # Include paths
 AM_CPPFLAGS = \
@@ -26,6 +27,10 @@ anjuta_token_test_LDADD = $(ANJUTA_LIBS)
 anjuta_token_test_SOURCES = anjuta-token-test.c \
                        ../anjuta-token.c
 
+anjuta_diff_renderer_test_CFLAGS = $(LIBANJUTA_CFLAGS)
+anjuta_diff_renderer_test_LDADD = $(LIBANJUTA_LIBS) $(ANJUTA_LIBS)
+anjuta_diff_renderer_test_SOURCES = anjuta-diff-renderer-test.c
+
 CLEANFILES = anjuta_token_test-anjuta-token.gcno \
              anjuta_token_test-anjuta-token-test.gcno \
              anjuta_token_test-anjuta-debug.gcno
diff --git a/libanjuta/tests/anjuta-diff-renderer-test.c b/libanjuta/tests/anjuta-diff-renderer-test.c
new file mode 100644
index 0000000..78dc01c
--- /dev/null
+++ b/libanjuta/tests/anjuta-diff-renderer-test.c
@@ -0,0 +1,124 @@
+/*
+ * anjuta-diff-renderer-test.c
+ *
+ * Copyright (C) 2013 - James Liggett
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libanjuta/anjuta-cell-renderer-diff.h>
+
+enum
+{
+       COL_DIFF,
+
+       NUM_COLS
+};
+
+static void
+on_window_destroy (GtkWidget *window, gpointer user_data)
+{
+       gtk_main_quit ();
+}
+
+int
+main (int argc, char **argv)
+{
+       GtkWidget *window;
+       GtkWidget *scrolled_window;
+       GtkWidget *tree_view;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer *renderer;
+       GtkListStore *list_store;
+       GtkTreeIter iter;
+       const gchar diff[] = 
+               "diff --git a/libanjuta/Makefile.am b/libanjuta/Makefile.am\n"
+               "index 4ac227e..d47c978 100644\n"
+               "--- a/libanjuta/Makefile.am\n"
+               "+++ b/libanjuta/Makefile.am\n"
+               "@@ -138,7 +138,9 @@ libanjuta_3_la_SOURCES= \\\n"
+               "        anjuta-close-button.c \\\n"
+               "        anjuta-close-button.h \\\n"
+               "        anjuta-modeline.c \\\n"
+               "-       anjuta-modeline.h\n"
+               "+       anjuta-modeline.h \\\n"
+               "+       anjuta-cell-renderer-diff.c \\\n"
+               "+       anjuta-cell-renderer-diff.h\n"
+               "\n"
+               "# Glade module\n"
+               "if ENABLE_GLADE_CATALOG\n";
+
+       const gchar non_diff[] = "non-diff text";
+       const gchar hunk_line[] = "@@";
+       const gchar broken_hunk[] = "@";
+
+       gtk_init (&argc, &argv);
+               
+
+       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       gtk_window_set_title (GTK_WINDOW (window), "Diff renderer test");
+
+       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+       tree_view = gtk_tree_view_new ();
+
+       gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
+
+       renderer = anjuta_cell_renderer_diff_new ();
+       column = gtk_tree_view_column_new ();
+
+       gtk_tree_view_column_pack_start (column, renderer, TRUE);
+       gtk_tree_view_column_add_attribute (column, renderer, "diff", COL_DIFF);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+
+       gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
+       gtk_container_add (GTK_CONTAINER (window), scrolled_window);
+
+       list_store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING);
+
+       /* Test general diffs */
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, diff, -1);
+
+       /* Test non-diff text */
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, non_diff, -1);
+
+       /* Test hunk line detection */
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, hunk_line, -1);
+
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, broken_hunk, -1);
+
+       /* Test empty and NULL strings */
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, "", -1);
+
+       gtk_list_store_append (list_store, &iter);
+       gtk_list_store_set (list_store, &iter, COL_DIFF, NULL, -1);
+
+       gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), 
+                                GTK_TREE_MODEL (list_store));
+
+       g_signal_connect (G_OBJECT (window), "destroy",
+                         G_CALLBACK (on_window_destroy),
+                         NULL);
+
+       gtk_widget_set_size_request (window, 650, 400);
+
+       gtk_widget_show_all (window);
+       gtk_main();
+
+       return 0;
+}
\ No newline at end of file


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