diff options
author | Sébastien Wilmet <swilmet@gnome.org> | 2014-12-15 14:53:29 +0100 |
---|---|---|
committer | Sébastien Wilmet <swilmet@gnome.org> | 2014-12-17 12:20:02 +0100 |
commit | 020258f85a4add53e9f04fce39f1ba3e89f9abae (patch) | |
tree | 9131a2651c344ce40fbbc51e628b80d2c6e95c97 /gtk | |
parent | 7ff3c6df80185e165e3bf6aa31bd014d1f8bf224 (diff) | |
download | gtk+-020258f85a4add53e9f04fce39f1ba3e89f9abae.tar.gz |
textview: add extend-selection signal
To be able to customize the double-click and triple-click behaviors, to
provide custom selection boundaries.
https://bugzilla.gnome.org/show_bug.cgi?id=111503
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtktextview.c | 135 | ||||
-rw-r--r-- | gtk/gtktextview.h | 24 |
2 files changed, 133 insertions, 26 deletions
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index ea8a78dabb..87bc39d136 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -281,6 +281,7 @@ enum SELECT_ALL, TOGGLE_CURSOR_VISIBLE, PREEDIT_CHANGED, + EXTEND_SELECTION, LAST_SIGNAL }; @@ -561,6 +562,12 @@ static void gtk_text_view_queue_draw_region (GtkWidget *widget, static void gtk_text_view_get_rendered_rect (GtkTextView *text_view, GdkRectangle *rect); +static gboolean gtk_text_view_extend_selection (GtkTextView *text_view, + GtkTextExtendSelection granularity, + const GtkTextIter *location, + GtkTextIter *start, + GtkTextIter *end); + /* FIXME probably need the focus methods. */ @@ -714,6 +721,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass) klass->paste_clipboard = gtk_text_view_paste_clipboard; klass->toggle_overwrite = gtk_text_view_toggle_overwrite; klass->create_buffer = gtk_text_view_create_buffer; + klass->extend_selection = gtk_text_view_extend_selection; /* * Properties @@ -1278,6 +1286,34 @@ G_GNUC_END_IGNORE_DEPRECATIONS G_TYPE_NONE, 1, G_TYPE_STRING); + /** + * GtkTextView::extend-selection: + * @text_view: the object which received the signal + * @granularity: the granularity type + * @location: the location where to extend the selection + * @start: where the selection should start + * @end: where the selection should end + * + * The ::extend-selection signal is emitted when the selection needs to be + * extended at @location. + * + * Returns: %GDK_EVENT_STOP to stop other handlers from being invoked for the + * event. %GDK_EVENT_PROPAGATE to propagate the event further. + * Since: 3.16 + */ + signals[EXTEND_SELECTION] = + g_signal_new (I_("extend-selection"), + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkTextViewClass, extend_selection), + _gtk_boolean_handled_accumulator, NULL, + NULL, /* generic marshaller */ + G_TYPE_BOOLEAN, 4, + GTK_TYPE_TEXT_EXTEND_SELECTION, + GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, + GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE); + /* * Key bindings */ @@ -6869,28 +6905,68 @@ drag_scan_timeout (gpointer data) return TRUE; } -/* - * Move @start and @end to the boundaries of the selection unit (indicated by - * @granularity) which contained @start initially. - * If the selction unit is SELECT_WORDS and @start is not contained in a word - * the selection is extended to all the white spaces between the end of the - * word preceding @start and the start of the one following. - */ static void -extend_selection (GtkTextView *text_view, - SelectionGranularity granularity, - GtkTextIter *start, - GtkTextIter *end) +extend_selection (GtkTextView *text_view, + SelectionGranularity granularity, + const GtkTextIter *location, + GtkTextIter *start, + GtkTextIter *end) { - *end = *start; + GtkTextExtendSelection extend_selection_granularity; + gboolean handled = FALSE; - if (granularity == SELECT_WORDS) + switch (granularity) { + case SELECT_CHARACTERS: + *start = *location; + *end = *location; + return; + + case SELECT_WORDS: + extend_selection_granularity = GTK_TEXT_EXTEND_SELECTION_WORD; + break; + + case SELECT_LINES: + extend_selection_granularity = GTK_TEXT_EXTEND_SELECTION_LINE; + break; + + default: + g_assert_not_reached (); + } + + g_signal_emit (text_view, + signals[EXTEND_SELECTION], 0, + extend_selection_granularity, + location, + start, + end, + &handled); + + if (!handled) + { + *start = *location; + *end = *location; + } +} + +static gboolean +gtk_text_view_extend_selection (GtkTextView *text_view, + GtkTextExtendSelection granularity, + const GtkTextIter *location, + GtkTextIter *start, + GtkTextIter *end) +{ + *start = *location; + *end = *location; + + switch (granularity) + { + case GTK_TEXT_EXTEND_SELECTION_WORD: if (gtk_text_iter_inside_word (start)) { if (!gtk_text_iter_starts_word (start)) gtk_text_iter_backward_visible_word_start (start); - + if (!gtk_text_iter_ends_word (end)) { if (!gtk_text_iter_forward_visible_word_end (end)) @@ -6901,6 +6977,11 @@ extend_selection (GtkTextView *text_view, { GtkTextIter tmp; + /* @start is not contained in a word: the selection is extended to all + * the white spaces between the end of the word preceding @start and + * the start of the one following. + */ + tmp = *start; if (gtk_text_iter_backward_visible_word_start (&tmp)) gtk_text_iter_forward_visible_word_end (&tmp); @@ -6922,9 +7003,9 @@ extend_selection (GtkTextView *text_view, else gtk_text_iter_forward_to_line_end (end); } - } - else if (granularity == SELECT_LINES) - { + break; + + case GTK_TEXT_EXTEND_SELECTION_LINE: if (gtk_text_view_starts_display_line (text_view, start)) { /* If on a display line boundary, we assume the user @@ -6939,13 +7020,18 @@ extend_selection (GtkTextView *text_view, * start, and move end to the end unless it's already there. */ gtk_text_view_backward_display_line_start (text_view, start); - + if (!gtk_text_view_starts_display_line (text_view, end)) gtk_text_view_forward_display_line_end (text_view, end); } + break; + + default: + g_return_val_if_reached (GDK_EVENT_STOP); } + + return GDK_EVENT_STOP; } - typedef struct { @@ -7061,8 +7147,8 @@ gtk_text_view_drag_gesture_update (GtkGestureDrag *gesture, get_iter_from_gesture (text_view, text_view->priv->drag_gesture, &cursor, NULL, NULL); - start = cursor; - extend_selection (text_view, data->granularity, &start, &end); + + extend_selection (text_view, data->granularity, &cursor, &start, &end); /* either the selection extends to the front, or end (or not) */ if (gtk_text_iter_compare (&cursor, &orig_start) < 0) @@ -7191,11 +7277,10 @@ gtk_text_view_start_selection_drag (GtkTextView *text_view, data->granularity = granularity; buffer = get_buffer (text_view); - + cursor = *iter; - ins = cursor; - - extend_selection (text_view, data->granularity, &ins, &bound); + extend_selection (text_view, data->granularity, &cursor, &ins, &bound); + orig_start = ins; orig_end = bound; gdk_event_get_state (event, &state); diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h index df1f5d9483..91396ba85d 100644 --- a/gtk/gtktextview.h +++ b/gtk/gtktextview.h @@ -82,6 +82,24 @@ typedef enum } GtkTextViewLayer; /** + * GtkTextExtendSelection: + * @GTK_TEXT_EXTEND_SELECTION_WORD: Selects the current word. It is triggered by + * a double-click for example. + * @GTK_TEXT_EXTEND_SELECTION_LINE: Selects the current line. It is triggered by + * a triple-click for example. + * + * Granularity types that extend the text selection. Use the + * #GtkTextView::extend-selection signal to customize the selection. + * + * Since: 3.16 + */ +typedef enum +{ + GTK_TEXT_EXTEND_SELECTION_WORD, + GTK_TEXT_EXTEND_SELECTION_LINE +} GtkTextExtendSelection; + +/** * GTK_TEXT_VIEW_PRIORITY_VALIDATE: * * The priority at which the text view validates onscreen lines @@ -160,6 +178,11 @@ struct _GtkTextViewClass void (* draw_layer) (GtkTextView *text_view, GtkTextViewLayer layer, cairo_t *cr); + gboolean (* extend_selection) (GtkTextView *text_view, + GtkTextExtendSelection granularity, + const GtkTextIter *location, + GtkTextIter *start, + GtkTextIter *end); /*< private >*/ @@ -169,7 +192,6 @@ struct _GtkTextViewClass void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); void (*_gtk_reserved5) (void); - void (*_gtk_reserved6) (void); }; GDK_AVAILABLE_IN_ALL |