[gnome-builder/wip/gtk4-port] plugins/spellcheck: setup spellcheck state on right click
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port] plugins/spellcheck: setup spellcheck state on right click
- Date: Fri, 8 Apr 2022 00:41:27 +0000 (UTC)
commit 5386e3ea0bce24f250c4c59ee5189a2dd1c5d67a
Author: Christian Hergert <chergert redhat com>
Date: Thu Apr 7 17:37:26 2022 -0700
plugins/spellcheck: setup spellcheck state on right click
.../spellcheck/gbp-spell-editor-page-addin.c | 165 +++++++++++++++++++--
1 file changed, 153 insertions(+), 12 deletions(-)
---
diff --git a/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
b/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
index 2388216b0..9e1c9ae76 100644
--- a/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
+++ b/src/plugins/spellcheck/gbp-spell-editor-page-addin.c
@@ -32,9 +32,12 @@
struct _GbpSpellEditorPageAddin
{
GObject parent_instance;
+ IdeEditorPage *page;
GbpSpellBufferAddin *buffer_addin;
+ GtkGestureClick *click;
GMenuModel *menu;
GSimpleActionGroup *actions;
+ char *spelling_word;
};
static void
@@ -43,16 +46,12 @@ gbp_spell_editor_page_addin_add (GSimpleAction *action,
gpointer user_data)
{
GbpSpellEditorPageAddin *self = user_data;
- const char *word;
IDE_ENTRY;
g_assert (G_IS_SIMPLE_ACTION (action));
- g_assert (param != NULL);
- g_assert (g_variant_is_of_type (param, G_VARIANT_TYPE_STRING));
- word = g_variant_get_string (param, NULL);
- gbp_spell_buffer_addin_add_word (self->buffer_addin, word);
+ gbp_spell_buffer_addin_add_word (self->buffer_addin, self->spelling_word);
IDE_EXIT;
}
@@ -63,25 +62,151 @@ gbp_spell_editor_page_addin_ignore (GSimpleAction *action,
gpointer user_data)
{
GbpSpellEditorPageAddin *self = user_data;
- const char *word;
IDE_ENTRY;
g_assert (G_IS_SIMPLE_ACTION (action));
- g_assert (param != NULL);
+
+ gbp_spell_buffer_addin_ignore_word (self->buffer_addin, self->spelling_word);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_spell_editor_page_addin_correct (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpSpellEditorPageAddin *self = user_data;
+ g_autofree char *slice = NULL;
+ IdeSourceView *view;
+ GtkTextBuffer *buffer;
+ const char *word;
+ GtkTextIter begin, end;
+
+ g_assert (GBP_IS_SPELL_EDITOR_PAGE_ADDIN (self));
g_assert (g_variant_is_of_type (param, G_VARIANT_TYPE_STRING));
+ g_assert (self->spelling_word != NULL);
+ view = ide_editor_page_get_view (self->page);
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
word = g_variant_get_string (param, NULL);
- gbp_spell_buffer_addin_ignore_word (self->buffer_addin, word);
- IDE_EXIT;
+ /* We don't deal with selections (yet?) */
+ if (gtk_text_buffer_get_selection_bounds (buffer, &begin, &end))
+ return;
+
+ if (!gtk_text_iter_starts_word (&begin))
+ gtk_text_iter_backward_word_start (&begin);
+
+ if (!gtk_text_iter_ends_word (&end))
+ gtk_text_iter_forward_word_end (&end);
+
+ slice = gtk_text_iter_get_slice (&begin, &end);
+
+ if (g_strcmp0 (slice, self->spelling_word) != 0)
+ {
+ g_debug ("Words do not match, will not replace.");
+ return;
+ }
+
+ gtk_text_buffer_begin_user_action (buffer);
+ gtk_text_buffer_delete (buffer, &begin, &end);
+ gtk_text_buffer_insert (buffer, &begin, word, -1);
+ gtk_text_buffer_end_user_action (buffer);
}
static const GActionEntry actions[] = {
- { "add", gbp_spell_editor_page_addin_add, "s" },
- { "ignore", gbp_spell_editor_page_addin_ignore, "s" },
+ { "add", gbp_spell_editor_page_addin_add },
+ { "ignore", gbp_spell_editor_page_addin_ignore },
+ { "correct", gbp_spell_editor_page_addin_correct, "s" },
};
+static void
+set_action_enabled (GSimpleActionGroup *group,
+ const char *name,
+ gboolean enabled)
+{
+ GAction *action;
+
+ if ((action = g_action_map_lookup_action (G_ACTION_MAP (group), name)))
+ {
+ if (G_IS_SIMPLE_ACTION (action))
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
+ }
+}
+
+static void
+on_click_pressed_cb (GtkGestureClick *click,
+ int n_press,
+ double x,
+ double y,
+ GbpSpellEditorPageAddin *self)
+{
+ GdkEventSequence *sequence;
+ g_auto(GStrv) corrections = NULL;
+ g_autofree char *word = NULL;
+ IdeSourceView *view;
+ GtkTextBuffer *buffer;
+ GdkEvent *event;
+ GtkTextIter iter, begin, end;
+ int buf_x, buf_y;
+
+ g_assert (GBP_IS_SPELL_EDITOR_PAGE_ADDIN (self));
+ g_assert (GTK_IS_GESTURE_CLICK (click));
+ g_assert (IDE_IS_EDITOR_PAGE (self->page));
+
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (click));
+ event = gtk_gesture_get_last_event (GTK_GESTURE (click), sequence);
+
+ if (n_press != 1 || !gdk_event_triggers_context_menu (event))
+ goto cleanup;
+
+ /* Move the cursor position to where the click occurred so that
+ * the context menu will be useful for the click location.
+ */
+ view = ide_editor_page_get_view (self->page);
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ if (gtk_text_buffer_get_selection_bounds (buffer, &begin, &end))
+ goto cleanup;
+
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
+ GTK_TEXT_WINDOW_WIDGET,
+ x, y, &buf_x, &buf_y);
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, buf_x, buf_y);
+ gtk_text_buffer_select_range (buffer, &iter, &iter);
+
+ /* Get the word under the cursor */
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+ begin = iter;
+ if (!gtk_text_iter_starts_word (&begin))
+ gtk_text_iter_backward_word_start (&begin);
+ end = begin;
+ if (!gtk_text_iter_ends_word (&end))
+ gtk_text_iter_forward_word_end (&end);
+ if (!gtk_text_iter_equal (&begin, &end) &&
+ gtk_text_iter_compare (&begin, &iter) <= 0 &&
+ gtk_text_iter_compare (&iter, &end) <= 0)
+ {
+ word = gtk_text_iter_get_slice (&begin, &end);
+
+ if (!gbp_spell_buffer_addin_check_spelling (self->buffer_addin, word))
+ corrections = gbp_spell_buffer_addin_list_corrections (self->buffer_addin, word);
+ else
+ g_clear_pointer (&word, g_free);
+ }
+
+cleanup:
+ g_free (self->spelling_word);
+ self->spelling_word = g_steal_pointer (&word);
+
+ set_action_enabled (self->actions, "add", self->spelling_word != NULL);
+ set_action_enabled (self->actions, "ignore", self->spelling_word != NULL);
+ editor_spell_menu_set_corrections (self->menu,
+ self->spelling_word,
+ (const char * const *)corrections);
+}
+
static void
gbp_spell_editor_page_addin_load (IdeEditorPageAddin *addin,
IdeEditorPage *page)
@@ -98,10 +223,21 @@ gbp_spell_editor_page_addin_load (IdeEditorPageAddin *addin,
buffer = ide_editor_page_get_buffer (page);
view = ide_editor_page_get_view (page);
-
buffer_addin = ide_buffer_addin_find_by_module_name (buffer, "spellcheck");
+
+ self->page = page;
self->buffer_addin = GBP_SPELL_BUFFER_ADDIN (buffer_addin);
+ self->click = GTK_GESTURE_CLICK (gtk_gesture_click_new ());
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->click), 0);
+ g_signal_connect_object (self->click,
+ "pressed",
+ G_CALLBACK (on_click_pressed_cb),
+ self,
+ 0);
+ gtk_widget_add_controller (GTK_WIDGET (view),
+ GTK_EVENT_CONTROLLER (self->click));
+
self->menu = editor_spell_menu_new ();
ide_source_view_append_menu (view, self->menu);
@@ -134,10 +270,15 @@ gbp_spell_editor_page_addin_unload (IdeEditorPageAddin *addin,
view = ide_editor_page_get_view (page);
ide_source_view_remove_menu (view, self->menu);
+ gtk_widget_remove_controller (GTK_WIDGET (view),
+ GTK_EVENT_CONTROLLER (self->click));
+ self->click = NULL;
+
g_clear_object (&self->menu);
g_clear_object (&self->actions);
self->buffer_addin = NULL;
+ self->page = NULL;
IDE_EXIT;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]