[geany/geany-plugins] 28c5c5: git-ui: Add tooltips for removed and modified lines
Colomban Wendling
git-noreply at xxxxx
Wed Feb 18 08:38:05 UTC 2015
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Tue, 07 Oct 2014 15:46:29 UTC
Commit: 28c5c5230d0928920cde17bd4db1c4e50ecefd55
https://github.com/geany/geany-plugins/commit/28c5c5230d0928920cde17bd4db1c4e50ecefd55
Log Message:
-----------
git-ui: Add tooltips for removed and modified lines
Modified Paths:
--------------
build/git-ui.m4
git-ui/src/ggu-plugin.c
Modified: build/git-ui.m4
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -3,7 +3,7 @@ AC_DEFUN([GP_CHECK_GITUI],
GP_ARG_DISABLE([GitUI], [auto])
GP_CHECK_PLUGIN_DEPS([GitUI], [GITUI],
- [$GP_GTK_PACKAGE
+ [$GP_GTK_PACKAGE >= 2.18
glib-2.0
libgit2])
Modified: git-ui/src/ggu-plugin.c
207 lines changed, 179 insertions(+), 28 deletions(-)
===================================================================
@@ -53,7 +53,8 @@ PLUGIN_SET_TRANSLATABLE_INFO (
* data that we know cannot ever be a valid job */
#define QUIT_THREAD_JOB ((AsyncBlobJob *) (&G_queue))
-#define MARKER_ALLOCATED_QTAG (g_quark_from_static_string ("ggu-git-marker-allocated"))
+#define RESOURCES_ALLOCATED_QTAG \
+ (g_quark_from_static_string ("ggu-git-resources-allocated"))
enum {
@@ -75,6 +76,18 @@ struct AsyncBlobJob {
gpointer user_data;
};
+typedef struct TooltipHunkData TooltipHunkData;
+struct TooltipHunkData {
+ gint line;
+ gboolean found;
+ GeanyDocument *doc;
+ const git_blob *file_blob;
+ GtkTooltip *tooltip;
+};
+
+#define TOOLTIP_HUNK_DATA_INIT(line, doc, blob, tooltip) \
+ { line, FALSE, doc, blob, tooltip }
+
/* cache */
static git_blob *G_file_blob = NULL;
@@ -93,11 +106,17 @@ static struct {
};
-static void on_git_dir_changed (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- gpointer user_data);
+static void on_git_dir_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data);
+static gboolean on_sci_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip,
+ gpointer user_data);
static void
@@ -286,11 +305,11 @@ allocate_marker (ScintillaObject *sci,
}
static gboolean
-allocate_markers (ScintillaObject *sci)
+allocate_resources (ScintillaObject *sci)
{
guint i;
- if (g_object_get_qdata (G_OBJECT (sci), MARKER_ALLOCATED_QTAG)) {
+ if (g_object_get_qdata (G_OBJECT (sci), RESOURCES_ALLOCATED_QTAG)) {
return TRUE;
}
@@ -312,16 +331,21 @@ allocate_markers (ScintillaObject *sci)
((G_markers[i].color & 0x0000ff) << 16));
}
- g_object_set_qdata (G_OBJECT (sci), MARKER_ALLOCATED_QTAG,
+ /* setup tooltips */
+ gtk_widget_set_has_tooltip (GTK_WIDGET (sci), TRUE);
+ g_signal_connect (sci, "query-tooltip",
+ G_CALLBACK (on_sci_query_tooltip), NULL);
+
+ g_object_set_qdata (G_OBJECT (sci), RESOURCES_ALLOCATED_QTAG,
sci /* anything non-NULL */);
return TRUE;
}
static void
-release_markers (ScintillaObject *sci)
+release_resources (ScintillaObject *sci)
{
- if (g_object_get_qdata (G_OBJECT (sci), MARKER_ALLOCATED_QTAG)) {
+ if (g_object_get_qdata (G_OBJECT (sci), RESOURCES_ALLOCATED_QTAG)) {
guint j;
for (j = 0; j < MARKER_COUNT; j++) {
@@ -330,11 +354,35 @@ release_markers (ScintillaObject *sci)
G_markers[j].num, SC_MARK_AVAILABLE);
}
}
- g_object_set_qdata (G_OBJECT (sci), MARKER_ALLOCATED_QTAG, NULL);
+ g_signal_handlers_disconnect_by_func (sci, on_sci_query_tooltip, NULL);
+ g_object_set_qdata (G_OBJECT (sci), RESOURCES_ALLOCATED_QTAG, NULL);
}
}
static int
+diff_blob_to_sci (const git_blob *old_blob,
+ ScintillaObject *sci,
+ git_diff_hunk_cb hunk_cb,
+ void *payload)
+{
+ git_diff_options opts;
+ const gchar *buf;
+ size_t len;
+
+ buf = (const gchar *) scintilla_send_message (sci, SCI_GETCHARACTERPOINTER,
+ 0, 0);
+ len = sci_get_length (sci);
+
+ /* no context lines, and no need to bother about binary checks */
+ git_diff_init_options (&opts, GIT_DIFF_OPTIONS_VERSION);
+ opts.context_lines = 0;
+ opts.flags = GIT_DIFF_FORCE_TEXT;
+
+ return git_diff_blob_to_buffer (old_blob, NULL, buf, len, NULL, &opts,
+ NULL, hunk_cb, NULL, payload);
+}
+
+static int
diff_hunk_cb (const git_diff_delta *delta,
const git_diff_hunk *hunk,
void *data)
@@ -356,6 +404,122 @@ diff_hunk_cb (const git_diff_delta *delta,
return 0;
}
+static GtkWidget *
+get_widget_for_blob_range (GeanyDocument *doc,
+ const git_blob *blob,
+ gint line_start,
+ gint n_lines)
+{
+ ScintillaObject *sci = editor_create_widget (doc->editor);
+ const GeanyIndentPrefs *iprefs = editor_get_indent_prefs (doc->editor);
+ gint width = 0;
+ gint height = 0;
+ gint i;
+ GtkAllocation alloc;
+
+ gtk_widget_get_allocation (GTK_WIDGET (doc->editor->sci), &alloc);
+
+ highlighting_set_styles (sci, doc->file_type);
+ if (iprefs->type == GEANY_INDENT_TYPE_BOTH) {
+ scintilla_send_message (sci, SCI_SETTABWIDTH, iprefs->hard_tab_width, 0);
+ } else {
+ scintilla_send_message (sci, SCI_SETTABWIDTH, iprefs->width, 0);
+ }
+ scintilla_send_message (sci, SCI_SETINDENT, iprefs->width, 0);
+
+ /* hide stuff we don't wanna see */
+ scintilla_send_message (sci, SCI_SETHSCROLLBAR, 0, 0);
+ scintilla_send_message (sci, SCI_SETVSCROLLBAR, 0, 0);
+ for (i = 0; i < SC_MAX_MARGIN; i++) {
+ scintilla_send_message (sci, SCI_SETMARGINWIDTHN, i, 0);
+ }
+
+ scintilla_send_message (sci, SCI_ADDTEXT,
+ (gulong) git_blob_rawsize (blob),
+ (glong) git_blob_rawcontent (blob));
+ scintilla_send_message (sci, SCI_SETFIRSTVISIBLELINE, line_start, 0);
+
+ /* compute the size of the area we want to see */
+ for (i = line_start; i < line_start + n_lines; i++) {
+ gint pos = sci_get_line_end_position (sci, i);
+ gint end_x = scintilla_send_message (sci, SCI_POINTXFROMPOSITION, 0, pos);
+
+ height += scintilla_send_message (sci, SCI_TEXTHEIGHT, i, 0);
+ width = MAX (width, end_x);
+
+ if (height > alloc.height) {
+ break;
+ }
+ }
+ gtk_widget_set_size_request (GTK_WIDGET (sci),
+ MIN (width, alloc.width),
+ MIN (height + 1, alloc.height));
+
+ return GTK_WIDGET (sci);
+}
+
+static int
+tooltip_diff_hunk_cb (const git_diff_delta *delta,
+ const git_diff_hunk *hunk,
+ void *data)
+{
+ TooltipHunkData *thd = data;
+
+ if (thd->found) {
+ return 1;
+ }
+
+ if (hunk->old_lines > 0 &&
+ thd->line >= hunk->new_start &&
+ thd->line < hunk->new_start + MAX (1, hunk->new_lines)) {
+ GtkWidget *old = get_widget_for_blob_range (thd->doc, thd->file_blob,
+ hunk->old_start - 1,
+ hunk->old_lines);
+
+ gtk_tooltip_set_custom (thd->tooltip, old);
+ thd->found = old != NULL;
+ }
+
+ return thd->found;
+}
+
+static gboolean
+on_sci_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip,
+ gpointer user_data)
+{
+ gint min_x;
+ gint max_x;
+ ScintillaObject *sci = (ScintillaObject *) widget;
+ GeanyDocument *doc = document_get_current ();
+ gboolean has_tooltip = FALSE;
+
+ g_return_val_if_fail (doc && doc->editor->sci == sci, FALSE);
+
+ min_x = scintilla_send_message (sci, SCI_GETMARGINWIDTHN, 0, 0);
+ max_x = min_x + scintilla_send_message (sci, SCI_GETMARGINWIDTHN, 1, 0);
+
+ if (x >= min_x && x <= max_x && G_file_blob) {
+ gint pos = scintilla_send_message (sci, SCI_POSITIONFROMPOINT, x, y);
+ gint line = sci_get_line_from_position (sci, pos);
+ gint mask = scintilla_send_message (sci, SCI_MARKERGET, line, 0);
+
+ if (mask & ((1 << G_markers[MARKER_LINE_CHANGED].num) |
+ (1 << G_markers[MARKER_LINE_REMOVED].num))) {
+ TooltipHunkData thd = TOOLTIP_HUNK_DATA_INIT (line + 1, doc, G_file_blob,
+ tooltip);
+
+ diff_blob_to_sci (G_file_blob, sci, tooltip_diff_hunk_cb, &thd);
+ has_tooltip = thd.found;
+ }
+ }
+
+ return has_tooltip;
+}
+
static void
update_diff (const gchar *path,
git_blob *blob,
@@ -364,11 +528,8 @@ update_diff (const gchar *path,
GeanyDocument *doc = document_get_current ();
if (doc && doc->id == GPOINTER_TO_UINT (data) &&
- blob && allocate_markers (doc->editor->sci)) {
+ blob && allocate_resources (doc->editor->sci)) {
ScintillaObject *sci = doc->editor->sci;
- git_diff_options opts;
- const gchar *buf;
- size_t len;
guint i;
/* clear previous markers */
@@ -376,17 +537,7 @@ update_diff (const gchar *path,
scintilla_send_message (sci, SCI_MARKERDELETEALL, G_markers[i].num, 0);
}
- buf = (const gchar *) scintilla_send_message (sci, SCI_GETCHARACTERPOINTER,
- 0, 0);
- len = sci_get_length (sci);
-
- /* no context lines, and no need to bother about binary checks */
- git_diff_init_options (&opts, GIT_DIFF_OPTIONS_VERSION);
- opts.context_lines = 0;
- opts.flags = GIT_DIFF_FORCE_TEXT;
-
- git_diff_blob_to_buffer (blob, NULL, buf, len, NULL, &opts,
- NULL, diff_hunk_cb, NULL, sci);
+ diff_blob_to_sci (blob, sci, diff_hunk_cb, sci);
}
}
@@ -519,7 +670,7 @@ plugin_cleanup (void)
}
foreach_document (i) {
- release_markers (documents[i]->editor->sci);
+ release_resources (documents[i]->editor->sci);
}
git_threads_shutdown ();
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list