[gspell/wip/entry-context-menu: 3/3] Entry: implement context menu



commit aad920bd37e98ebdc5a6a61e312a3a8a241ce770
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Nov 25 14:37:46 2016 +0100

    Entry: implement context menu

 gspell/gspell-entry.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/gspell/gspell-entry.c b/gspell/gspell-entry.c
index 13d1a43..3abf082 100644
--- a/gspell/gspell-entry.c
+++ b/gspell/gspell-entry.c
@@ -48,6 +48,9 @@ struct _GspellEntry
         */
        GSList *misspelled_words;
 
+       /* The position is in characters, not in bytes. */
+       gint popup_char_position;
+
        gulong notify_attributes_handler_id;
        guint notify_attributes_idle_id;
 
@@ -416,6 +419,82 @@ notify_buffer_cb (GtkEntry    *gtk_entry,
        emit_changed_signal (gspell_entry);
 }
 
+/* Free the return value with _gspell_entry_word_free(). */
+static GspellEntryWord *
+get_entry_word_at_popup_position (GspellEntry *gspell_entry)
+{
+       gint pos;
+       GSList *words;
+       GSList *l;
+       GspellEntryWord *entry_word = NULL;
+
+       pos = gspell_entry->popup_char_position;
+
+       words = _gspell_entry_utils_get_words (gspell_entry->entry);
+
+       for (l = words; l != NULL; l = l->next)
+       {
+               GspellEntryWord *cur_word = l->data;
+
+               if (cur_word->char_start <= pos && pos <= cur_word->char_end)
+               {
+                       entry_word = cur_word;
+                       l->data = NULL;
+                       break;
+               }
+       }
+
+       g_slist_free_full (words, _gspell_entry_word_free);
+       return entry_word;
+}
+
+static gboolean
+popup_menu_cb (GtkEntry    *gtk_entry,
+              GspellEntry *gspell_entry)
+{
+       /* Save the position before popping up the menu, otherwise it will
+        * contain the wrong set of suggestions.
+        */
+       gspell_entry->popup_char_position = gtk_editable_get_position (GTK_EDITABLE (gtk_entry));
+
+       return FALSE;
+}
+
+static gboolean
+button_press_event_cb (GtkEntry       *gtk_entry,
+                      GdkEventButton *event,
+                      GspellEntry    *gspell_entry)
+{
+       if (event->button == GDK_BUTTON_SECONDARY)
+       {
+               gspell_entry->popup_char_position =
+                       _gspell_entry_utils_get_char_position_at_event (gtk_entry, event);
+       }
+
+       return GDK_EVENT_PROPAGATE;
+}
+
+static void
+populate_popup_cb (GtkEntry    *gtk_entry,
+                  GtkWidget   *popup,
+                  GspellEntry *gspell_entry)
+{
+       GspellEntryWord *word;
+
+       word = get_entry_word_at_popup_position (gspell_entry);
+
+       if (word != NULL)
+       {
+               g_message ("Populate popup at word “%s”.", word->word_str);
+       }
+       else
+       {
+               g_message ("Populate popup not inside a word.");
+       }
+
+       _gspell_entry_word_free (word);
+}
+
 static void
 set_entry (GspellEntry *gspell_entry,
           GtkEntry    *gtk_entry)
@@ -447,6 +526,21 @@ set_entry (GspellEntry *gspell_entry,
                                  G_CALLBACK (notify_attributes_cb),
                                  gspell_entry);
 
+       g_signal_connect (gtk_entry,
+                         "popup-menu",
+                         G_CALLBACK (popup_menu_cb),
+                         gspell_entry);
+
+       g_signal_connect (gtk_entry,
+                         "button-press-event",
+                         G_CALLBACK (button_press_event_cb),
+                         gspell_entry);
+
+       g_signal_connect (gtk_entry,
+                         "populate-popup",
+                         G_CALLBACK (populate_popup_cb),
+                         gspell_entry);
+
        update_buffer (gspell_entry);
 
        g_object_notify (G_OBJECT (gspell_entry), "entry");


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