From 7d59e50bb880209f29c95676d7cfd6b64de10553 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Fri, 23 Dec 2005 13:23:35 +0000 Subject: [PATCH] Added basic linkdrag --- gnoemoe/widgets/gm-world-text-view.c | 88 ++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/gnoemoe/widgets/gm-world-text-view.c b/gnoemoe/widgets/gm-world-text-view.c index 9d4130d..9723c90 100644 --- a/gnoemoe/widgets/gm-world-text-view.c +++ b/gnoemoe/widgets/gm-world-text-view.c @@ -1,6 +1,6 @@ #include #include - +#include #include "gm-world-text-view.h" #include "../gm-color-table.h" #include "../gm-marshal.h" @@ -24,11 +24,15 @@ void on_gm_world_text_view_color_table_font_changed(GmColorTable *table, gchar *font_description, GmWorldTextView *view); void on_gm_world_text_view_populate_popup(GmWorldTextView *view, GtkMenu *menu, gpointer user_data); +void on_gm_world_text_view_drag_data_get(GmWorldTextView *view, + GdkDragContext *context, GtkSelectionData *data, guint info, + guint time, gpointer user_data); void gm_world_text_view_create_tags(GmWorldTextView *view); void gm_world_text_view_init_tags(GmWorldTextView *view); void gm_world_text_view_update_font(GmWorldTextView *view); + #define GM_WORLD_TEXT_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GM_TYPE_WORLD_TEXT_VIEW, GmWorldTextViewPrivate)) #define GM_WORLD_TEXT_VIEW_BUFFER(view) gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)) @@ -49,6 +53,11 @@ struct _GmWorldTextViewPrivate { gint max_lines; GmWorldTextViewInsertInfo last_info; GmColorTable *color_table; + gboolean drag_url; + gchar *drag_url_text; + guint drag_x; + guint drag_y; + GtkTargetList *source_target_list; }; /* Signals */ @@ -72,6 +81,7 @@ gm_world_text_view_finalize(GObject *object) { g_list_free(view->priv->last_info.tags); g_free(view->priv->last_info.text); + gtk_target_list_unref(view->priv->source_target_list); G_OBJECT_CLASS(gm_world_text_view_parent_class)->finalize(object); } @@ -107,6 +117,15 @@ gm_world_text_view_class_init(GmWorldTextViewClass *klass) { g_type_class_add_private(object_class, sizeof(GmWorldTextViewPrivate)); } +enum { + DRAG_URL, + NUM_TARGETS +}; + +static const GtkTargetEntry drag_targets[] = { + {"_NETSCAPE_URL", 0, DRAG_URL} +}; + static void gm_world_text_view_init(GmWorldTextView *view) { view->priv = GM_WORLD_TEXT_VIEW_GET_PRIVATE(view); @@ -138,11 +157,16 @@ gm_world_text_view_init(GmWorldTextView *view) { view->priv->last_info.tags = NULL; view->priv->last_info.text = NULL; + view->priv->source_target_list = gtk_target_list_new(drag_targets, + NUM_TARGETS); + // Connect style set signal g_signal_connect(view, "style-set", G_CALLBACK(on_gm_world_text_view_style_set), NULL); g_signal_connect(view, "populate_popup", G_CALLBACK(on_gm_world_text_view_populate_popup), NULL); + g_signal_connect(view, "drag_data_get", + G_CALLBACK(on_gm_world_text_view_drag_data_get), NULL); } /* Private functions */ @@ -527,7 +551,7 @@ gm_world_text_view_tags_overlap(GtkTextTag *t1, GtkTextTag *t2) { return TRUE; } - i++; + ++i; } return FALSE; @@ -886,13 +910,52 @@ gboolean on_gm_world_text_view_url_event(GtkTextTag *tag, GObject *object, GdkEvent *event, GtkTextIter *iter, GmWorldTextView *view) { GtkTextIter start, end; - gchar *str; + gchar *str = NULL; GtkTextBuffer *buffer = GM_WORLD_TEXT_VIEW_BUFFER(view); + + start = end = *iter; + + if (gtk_text_iter_backward_to_tag_toggle(&start, tag) && + gtk_text_iter_forward_to_tag_toggle(&end, tag)) { + str = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); + } + if (str == NULL) { + return FALSE; + } + + if (event->type == GDK_MOTION_NOTIFY && view->priv->drag_url && + !(event->motion.state & GDK_CONTROL_MASK) && + gtk_drag_check_threshold(GTK_WIDGET(view), view->priv->drag_x, + view->priv->drag_y, event->motion.x, event->motion.y)) { + view->priv->drag_url = FALSE; + view->priv->drag_url_text = g_strdup(str); + gtk_drag_begin(GTK_WIDGET(view), view->priv->source_target_list, + GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK, + 1, event); + + GM_DEBUG("Drag started!"); + } + + if (event->type == GDK_BUTTON_PRESS && + !(event->button.state & GDK_CONTROL_MASK)) { + GM_DEBUG("Possible drag init!"); + view->priv->drag_x = event->button.x; + view->priv->drag_y = event->button.y; + view->priv->drag_url = TRUE; + } + + if (event->type == GDK_BUTTON_RELEASE && view->priv->drag_url && + event->button.button == 1) { + GM_DEBUG("Drag stopped!"); + view->priv->drag_url = FALSE; + } + /* If the link is being selected, don't do anything. */ gtk_text_buffer_get_selection_bounds(buffer, &start, &end); if (gtk_text_iter_get_offset(&start) != gtk_text_iter_get_offset(&end)) { + g_free(str); return FALSE; } @@ -901,12 +964,11 @@ on_gm_world_text_view_url_event(GtkTextTag *tag, GObject *object, if (gtk_text_iter_backward_to_tag_toggle(&start, tag) && gtk_text_iter_forward_to_tag_toggle(&end, tag)) { - str = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); g_signal_emit(view, world_text_view_signals[URL_ACTIVATE], 0, str); - g_free(str); } } + g_free(str); return FALSE; } @@ -994,7 +1056,11 @@ on_gm_world_text_view_event(GmWorldTextView *view, GdkEventMotion *event, if (type != GTK_TEXT_WINDOW_TEXT) { return FALSE; } - + + if (event->type != GDK_MOTION_NOTIFY) { + return FALSE; + } + /* Get where the pointer really is. */ win = gtk_text_view_get_window(GTK_TEXT_VIEW(view), type); gdk_window_get_pointer(win, &x, &y, NULL); @@ -1088,3 +1154,13 @@ on_gm_world_text_view_color_table_font_changed(GmColorTable *table, gchar *font_description, GmWorldTextView *view) { gm_world_text_view_update_font(view); } + +void on_gm_world_text_view_drag_data_get(GmWorldTextView *view, + GdkDragContext *context, GtkSelectionData *data, guint info, + guint time, gpointer user_data) { + switch (info) { + case DRAG_URL: + gtk_selection_data_set_text(data, view->priv->drag_url_text, -1); + break; + } +}