[gspell/wip/entry-context-menu: 1/2] InlineCheckerTextBuffer: make suggestions context menu re-usable
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gspell/wip/entry-context-menu: 1/2] InlineCheckerTextBuffer: make suggestions context menu re-usable
- Date: Sat, 26 Nov 2016 15:00:12 +0000 (UTC)
commit f2a4d8951b00cd66861dfb040f5bc552551995e4
Author: Sébastien Wilmet <swilmet gnome org>
Date: Sat Nov 26 13:47:19 2016 +0100
InlineCheckerTextBuffer: make suggestions context menu re-usable
So that it can be used in GspellEntry.
gspell/gspell-context-menu.c | 217 +++++++++++++++++++++++++++-
gspell/gspell-context-menu.h | 10 ++
gspell/gspell-inline-checker-text-buffer.c | 192 ++++---------------------
3 files changed, 253 insertions(+), 166 deletions(-)
---
diff --git a/gspell/gspell-context-menu.c b/gspell/gspell-context-menu.c
index 46cc587..1e4d55f 100644
--- a/gspell/gspell-context-menu.c
+++ b/gspell/gspell-context-menu.c
@@ -22,8 +22,11 @@
#include <glib/gi18n-lib.h>
#define LANGUAGE_DATA_KEY "gspell-language-data-key"
+#define SUGGESTION_DATA_KEY "gspell-suggestion-data-key"
+
+typedef struct _LanguageData LanguageData;
+typedef struct _SuggestionData SuggestionData;
-typedef struct _LanguageData LanguageData;
struct _LanguageData
{
const GspellLanguage *lang;
@@ -31,6 +34,30 @@ struct _LanguageData
gpointer user_data;
};
+struct _SuggestionData
+{
+ GspellChecker *checker;
+ gchar *misspelled_word;
+
+ gchar *suggested_word;
+ GspellSuggestionActivatedCallback callback;
+ gpointer user_data;
+};
+
+static void
+suggestion_data_free (gpointer data)
+{
+ SuggestionData *suggestion_data = data;
+
+ if (suggestion_data != NULL)
+ {
+ g_clear_object (&suggestion_data->checker);
+ g_free (suggestion_data->misspelled_word);
+ g_free (suggestion_data->suggested_word);
+ g_free (suggestion_data);
+ }
+}
+
static void
activate_language_cb (GtkWidget *menu_item)
{
@@ -126,4 +153,192 @@ _gspell_context_menu_get_language_menu_item (const GspellLanguage *cu
return menu_item;
}
+static void
+activate_suggestion_cb (GtkWidget *menu_item)
+{
+ SuggestionData *data;
+
+ data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ if (data->callback != NULL)
+ {
+ data->callback (data->suggested_word, data->user_data);
+ }
+}
+
+static void
+ignore_all_cb (GtkWidget *menu_item)
+{
+ SuggestionData *data;
+
+ data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ gspell_checker_add_word_to_session (data->checker,
+ data->misspelled_word,
+ -1);
+}
+
+static void
+add_to_dictionary_cb (GtkWidget *menu_item)
+{
+ SuggestionData *data;
+
+ data = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_DATA_KEY);
+ g_return_if_fail (data != NULL);
+
+ gspell_checker_add_word_to_personal (data->checker,
+ data->misspelled_word,
+ -1);
+}
+
+static GtkWidget *
+get_suggestion_menu (GspellChecker *checker,
+ const gchar *misspelled_word,
+ GspellSuggestionActivatedCallback callback,
+ gpointer user_data)
+{
+ GtkWidget *top_menu;
+ GtkWidget *menu_item;
+ GSList *suggestions = NULL;
+ SuggestionData *data;
+
+ top_menu = gtk_menu_new ();
+
+ suggestions = gspell_checker_get_suggestions (checker, misspelled_word, -1);
+
+ if (suggestions == NULL)
+ {
+ /* No suggestions. Put something in the menu anyway... */
+ menu_item = gtk_menu_item_new_with_label (_("(no suggested words)"));
+ gtk_widget_set_sensitive (menu_item, FALSE);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (top_menu), menu_item);
+ }
+ else
+ {
+ GtkWidget *menu = top_menu;
+ gint count = 0;
+ GSList *l;
+
+ /* Build a set of menus with suggestions. */
+ for (l = suggestions; l != NULL; l = l->next)
+ {
+ gchar *suggested_word = l->data;
+ GtkWidget *label;
+ gchar *label_text;
+
+ if (count == 10)
+ {
+ /* Separator */
+ menu_item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+ menu_item = gtk_menu_item_new_with_mnemonic (_("_More…"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+ menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
+ count = 0;
+ }
+
+ label_text = g_strdup_printf ("<b>%s</b>", suggested_word);
+
+ label = gtk_label_new (label_text);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+ menu_item = gtk_menu_item_new ();
+ gtk_container_add (GTK_CONTAINER (menu_item), label);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+ data = g_new0 (SuggestionData, 1);
+ data->suggested_word = g_strdup (suggested_word);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ g_object_set_data_full (G_OBJECT (menu_item),
+ SUGGESTION_DATA_KEY,
+ data,
+ suggestion_data_free);
+
+ g_signal_connect (menu_item,
+ "activate",
+ G_CALLBACK (activate_suggestion_cb),
+ NULL);
+
+ g_free (label_text);
+ count++;
+ }
+ }
+
+ g_slist_free_full (suggestions, g_free);
+
+ /* Separator */
+ menu_item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
+
+ /* Ignore all */
+ menu_item = gtk_menu_item_new_with_mnemonic (_("_Ignore All"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
+
+ data = g_new0 (SuggestionData, 1);
+ data->checker = g_object_ref (checker);
+ data->misspelled_word = g_strdup (misspelled_word);
+
+ g_object_set_data_full (G_OBJECT (menu_item),
+ SUGGESTION_DATA_KEY,
+ data,
+ suggestion_data_free);
+
+ g_signal_connect (menu_item,
+ "activate",
+ G_CALLBACK (ignore_all_cb),
+ NULL);
+
+ /* Add to Dictionary */
+ menu_item = gtk_menu_item_new_with_mnemonic (_("_Add"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
+
+ data = g_new0 (SuggestionData, 1);
+ data->checker = g_object_ref (checker);
+ data->misspelled_word = g_strdup (misspelled_word);
+
+ g_object_set_data_full (G_OBJECT (menu_item),
+ SUGGESTION_DATA_KEY,
+ data,
+ suggestion_data_free);
+
+ g_signal_connect (menu_item,
+ "activate",
+ G_CALLBACK (add_to_dictionary_cb),
+ NULL);
+
+ return top_menu;
+}
+
+GtkMenuItem *
+_gspell_context_menu_get_suggestions_menu_item (GspellChecker *checker,
+ const gchar *misspelled_word,
+ GspellSuggestionActivatedCallback callback,
+ gpointer user_data)
+{
+ GtkWidget *suggestion_menu;
+ GtkMenuItem *menu_item;
+
+ g_return_val_if_fail (GSPELL_IS_CHECKER (checker), NULL);
+ g_return_val_if_fail (misspelled_word != NULL, NULL);
+
+ suggestion_menu = get_suggestion_menu (checker,
+ misspelled_word,
+ callback,
+ user_data);
+
+ menu_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions…")));
+ gtk_menu_item_set_submenu (menu_item, suggestion_menu);
+ gtk_widget_show_all (GTK_WIDGET (menu_item));
+
+ return menu_item;
+}
+
/* ex:set ts=8 noet: */
diff --git a/gspell/gspell-context-menu.h b/gspell/gspell-context-menu.h
index 5359e15..ee2e430 100644
--- a/gspell/gspell-context-menu.h
+++ b/gspell/gspell-context-menu.h
@@ -21,6 +21,7 @@
#define GSPELL_CONTEXT_MENU_H
#include <gtk/gtk.h>
+#include "gspell-checker.h"
#include "gspell-language.h"
G_BEGIN_DECLS
@@ -28,11 +29,20 @@ G_BEGIN_DECLS
typedef void (*GspellLanguageActivatedCallback) (const GspellLanguage *lang,
gpointer user_data);
+typedef void (*GspellSuggestionActivatedCallback) (const gchar *suggested_word,
+ gpointer user_data);
+
G_GNUC_INTERNAL
GtkMenuItem * _gspell_context_menu_get_language_menu_item (const GspellLanguage
*current_language,
GspellLanguageActivatedCallback callback,
gpointer user_data);
+G_GNUC_INTERNAL
+GtkMenuItem * _gspell_context_menu_get_suggestions_menu_item (GspellChecker *checker,
+ const gchar
*misspelled_word,
+ GspellSuggestionActivatedCallback callback,
+ gpointer
user_data);
+
G_END_DECLS
#endif /* GSPELL_CONTEXT_MENU_H */
diff --git a/gspell/gspell-inline-checker-text-buffer.c b/gspell/gspell-inline-checker-text-buffer.c
index 038f315..c0fbf45 100644
--- a/gspell/gspell-inline-checker-text-buffer.c
+++ b/gspell/gspell-inline-checker-text-buffer.c
@@ -28,6 +28,7 @@
#include <glib/gi18n-lib.h>
#include "gspellregion.h"
#include "gspell-checker.h"
+#include "gspell-context-menu.h"
#include "gspell-text-buffer.h"
#include "gspell-text-iter.h"
#include "gspell-utils.h"
@@ -76,8 +77,7 @@ typedef enum
ADJUST_MODE_INCLUDE_NEIGHBORS,
} AdjustMode;
-#define INLINE_CHECKER_TEXT_BUFFER_KEY "GspellInlineCheckerTextBufferID"
-#define SUGGESTION_KEY "GspellInlineSuggestionID"
+#define INLINE_CHECKER_TEXT_BUFFER_KEY "GspellInlineCheckerTextBufferID"
/* Timeout durations in milliseconds. Writing and deleting text should be smooth
* and responsive.
@@ -739,59 +739,17 @@ get_word_extents_at_click_position (GspellInlineCheckerTextBuffer *spell,
}
static void
-add_to_dictionary_cb (GtkWidget *menu_item,
- GspellInlineCheckerTextBuffer *spell)
-{
- GtkTextIter start;
- GtkTextIter end;
- gchar *word;
-
- if (!get_word_extents_at_click_position (spell, &start, &end))
- {
- return;
- }
-
- word = gtk_text_buffer_get_text (spell->buffer, &start, &end, FALSE);
-
- if (spell->spell_checker != NULL)
- {
- gspell_checker_add_word_to_personal (spell->spell_checker, word, -1);
- }
-
- g_free (word);
-}
-
-static void
-ignore_all_cb (GtkWidget *menu_item,
- GspellInlineCheckerTextBuffer *spell)
+suggestion_activated_cb (const gchar *suggested_word,
+ gpointer user_data)
{
+ GspellInlineCheckerTextBuffer *spell;
GtkTextIter start;
GtkTextIter end;
- gchar *word;
-
- if (!get_word_extents_at_click_position (spell, &start, &end))
- {
- return;
- }
-
- word = gtk_text_buffer_get_text (spell->buffer, &start, &end, FALSE);
-
- if (spell->spell_checker != NULL)
- {
- gspell_checker_add_word_to_session (spell->spell_checker, word, -1);
- }
+ gchar *old_word;
- g_free (word);
-}
+ g_return_if_fail (GSPELL_IS_INLINE_CHECKER_TEXT_BUFFER (user_data));
-static void
-replace_word_cb (GtkWidget *menu_item,
- GspellInlineCheckerTextBuffer *spell)
-{
- GtkTextIter start;
- GtkTextIter end;
- gchar *old_word;
- const gchar *new_word;
+ spell = GSPELL_INLINE_CHECKER_TEXT_BUFFER (user_data);
if (!get_word_extents_at_click_position (spell, &start, &end))
{
@@ -800,13 +758,10 @@ replace_word_cb (GtkWidget *menu_item,
old_word = gtk_text_buffer_get_text (spell->buffer, &start, &end, FALSE);
- new_word = g_object_get_data (G_OBJECT (menu_item), SUGGESTION_KEY);
- g_return_if_fail (new_word != NULL);
-
gtk_text_buffer_begin_user_action (spell->buffer);
gtk_text_buffer_delete (spell->buffer, &start, &end);
- gtk_text_buffer_insert (spell->buffer, &start, new_word, -1);
+ gtk_text_buffer_insert (spell->buffer, &start, suggested_word, -1);
gtk_text_buffer_end_user_action (spell->buffer);
@@ -814,121 +769,20 @@ replace_word_cb (GtkWidget *menu_item,
{
gspell_checker_set_correction (spell->spell_checker,
old_word, -1,
- new_word, -1);
+ suggested_word, -1);
}
g_free (old_word);
}
-static GtkWidget *
-get_suggestion_menu (GspellInlineCheckerTextBuffer *spell,
- const gchar *word)
-{
- GtkWidget *top_menu;
- GtkWidget *menu_item;
- GSList *suggestions = NULL;
-
- top_menu = gtk_menu_new ();
-
- if (spell->spell_checker != NULL)
- {
- suggestions = gspell_checker_get_suggestions (spell->spell_checker, word, -1);
- }
-
- if (suggestions == NULL)
- {
- /* No suggestions. Put something in the menu anyway... */
- menu_item = gtk_menu_item_new_with_label (_("(no suggested words)"));
- gtk_widget_set_sensitive (menu_item, FALSE);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (top_menu), menu_item);
- }
- else
- {
- GtkWidget *menu = top_menu;
- gint count = 0;
- GSList *l;
-
- /* Build a set of menus with suggestions. */
- for (l = suggestions; l != NULL; l = l->next)
- {
- gchar *suggested_word = l->data;
- GtkWidget *label;
- gchar *label_text;
-
- if (count == 10)
- {
- /* Separator */
- menu_item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-
- menu_item = gtk_menu_item_new_with_mnemonic (_("_More…"));
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-
- menu = gtk_menu_new ();
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
- count = 0;
- }
-
- label_text = g_strdup_printf ("<b>%s</b>", suggested_word);
-
- label = gtk_label_new (label_text);
- gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
- gtk_widget_set_halign (label, GTK_ALIGN_START);
-
- menu_item = gtk_menu_item_new ();
- gtk_container_add (GTK_CONTAINER (menu_item), label);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-
- g_object_set_data_full (G_OBJECT (menu_item),
- SUGGESTION_KEY,
- g_strdup (suggested_word),
- g_free);
-
- g_signal_connect (menu_item,
- "activate",
- G_CALLBACK (replace_word_cb),
- spell);
-
- g_free (label_text);
- count++;
- }
- }
-
- g_slist_free_full (suggestions, g_free);
-
- /* Separator */
- menu_item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
-
- /* Ignore all */
- menu_item = gtk_menu_item_new_with_mnemonic (_("_Ignore All"));
- gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
-
- g_signal_connect (menu_item,
- "activate",
- G_CALLBACK (ignore_all_cb),
- spell);
-
- /* Add to Dictionary */
- menu_item = gtk_menu_item_new_with_mnemonic (_("_Add"));
- gtk_menu_shell_append (GTK_MENU_SHELL (top_menu), menu_item);
-
- g_signal_connect (menu_item,
- "activate",
- G_CALLBACK (add_to_dictionary_cb),
- spell);
-
- return top_menu;
-}
-
void
_gspell_inline_checker_text_buffer_populate_popup (GspellInlineCheckerTextBuffer *spell,
GtkMenu *menu)
{
- GtkWidget *menu_item;
+ GtkMenuItem *menu_item;
GtkTextIter start;
GtkTextIter end;
- gchar *word;
+ gchar *misspelled_word;
if (!get_word_extents_at_click_position (spell, &start, &end))
{
@@ -940,16 +794,24 @@ _gspell_inline_checker_text_buffer_populate_popup (GspellInlineCheckerTextBuffer
return;
}
+ if (spell->spell_checker == NULL)
+ {
+ return;
+ }
+
/* Prepend suggestions */
- menu_item = gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions…"));
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- word = gtk_text_buffer_get_text (spell->buffer, &start, &end, FALSE);
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
- get_suggestion_menu (spell, word));
- g_free (word);
+ misspelled_word = gtk_text_buffer_get_text (spell->buffer, &start, &end, FALSE);
+
+ menu_item = _gspell_context_menu_get_suggestions_menu_item (spell->spell_checker,
+ misspelled_word,
+ suggestion_activated_cb,
+ spell);
+
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu),
+ GTK_WIDGET (menu_item));
- gtk_widget_show_all (menu_item);
+ g_free (misspelled_word);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]