[gspell/wip/entry-context-menu: 5/6] TextView: make language context menu re-usable



commit a0817878d1ffeec1a378f998c6c0a024205113d2
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Nov 26 11:24:24 2016 +0100

    TextView: make language context menu re-usable
    
    It will be used for both GtkTextView and GtkEntry.

 docs/reference/Makefile.am   |    1 +
 gspell/Makefile.am           |    2 +
 gspell/gspell-context-menu.c |  129 ++++++++++++++++++++++++++++++++++++++++++
 gspell/gspell-context-menu.h |   40 +++++++++++++
 gspell/gspell-text-view.c    |   95 ++++++-------------------------
 po/POTFILES.in               |    1 +
 6 files changed, 192 insertions(+), 76 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index da88172..d3f17df 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -32,6 +32,7 @@ IGNORE_HFILES =                                       \
        gspell.h                                \
        gspellregion.h                          \
        gspell-checker-private.h                \
+       gspell-context-menu.h                   \
        gspell-entry-private.h                  \
        gspell-entry-utils.h                    \
        gspell-init.h                           \
diff --git a/gspell/Makefile.am b/gspell/Makefile.am
index e8e87f1..825d6cf 100644
--- a/gspell/Makefile.am
+++ b/gspell/Makefile.am
@@ -46,6 +46,7 @@ gspell_private_headers =                      \
        gconstructor.h                          \
        gspellregion.h                          \
        gspell-checker-private.h                \
+       gspell-context-menu.h                   \
        gspell-entry-private.h                  \
        gspell-entry-utils.h                    \
        gspell-init.h                           \
@@ -55,6 +56,7 @@ gspell_private_headers =                      \
 
 gspell_private_c_files =                       \
        gspellregion.c                          \
+       gspell-context-menu.c                   \
        gspell-entry-utils.c                    \
        gspell-init.c                           \
        gspell-inline-checker-text-buffer.c     \
diff --git a/gspell/gspell-context-menu.c b/gspell/gspell-context-menu.c
new file mode 100644
index 0000000..677968c
--- /dev/null
+++ b/gspell/gspell-context-menu.c
@@ -0,0 +1,129 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2016 - Sébastien Wilmet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "gspell-context-menu.h"
+#include <glib/gi18n-lib.h>
+
+#define LANGUAGE_DATA_KEY "gspell-language-data-key"
+
+typedef struct _LanguageData LanguageData;
+struct _LanguageData
+{
+       const GspellLanguage *lang;
+       GspellLanguageActivatedCallback callback;
+       gpointer user_data;
+};
+
+static void
+activate_language_cb (GtkWidget *menu_item)
+{
+       LanguageData *data;
+
+       data = g_object_get_data (G_OBJECT (menu_item), LANGUAGE_DATA_KEY);
+       if (data == NULL)
+       {
+               g_return_if_reached ();
+       }
+
+       data->callback (data->lang, data->user_data);
+}
+
+static GtkWidget *
+get_language_menu (const GspellLanguage            *current_language,
+                  GspellLanguageActivatedCallback  callback,
+                  gpointer                         user_data)
+{
+       GtkWidget *menu;
+       const GList *languages;
+       const GList *l;
+
+       menu = gtk_menu_new ();
+
+       languages = gspell_language_get_available ();
+       for (l = languages; l != NULL; l = l->next)
+       {
+               const GspellLanguage *lang = l->data;
+               const gchar *lang_name;
+               GtkWidget *menu_item;
+               LanguageData *data;
+
+               lang_name = gspell_language_get_name (lang);
+
+               if (lang == current_language)
+               {
+                       /* Do not create a group. Just mark the current language
+                        * as active.
+                        *
+                        * With a group, the first language in the list gets
+                        * activated, which changes the GspellChecker language
+                        * before we arrive to the current_language.
+                        *
+                        * Also, having a bullet only for the current_language is
+                        * sufficient (to be like in Firefox), the menu is
+                        * anyway ephemeral. No need to have an empty bullet for
+                        * all the other languages.
+                        */
+                       menu_item = gtk_radio_menu_item_new_with_label (NULL, lang_name);
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
+               }
+               else
+               {
+                       menu_item = gtk_menu_item_new_with_label (lang_name);
+               }
+
+               gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+               data = g_new0 (LanguageData, 1);
+               data->lang = lang;
+               data->callback = callback;
+               data->user_data = user_data;
+
+               g_object_set_data_full (G_OBJECT (menu_item),
+                                       LANGUAGE_DATA_KEY,
+                                       data,
+                                       g_free);
+
+               g_signal_connect (menu_item,
+                                 "activate",
+                                 G_CALLBACK (activate_language_cb),
+                                 NULL);
+       }
+
+       return menu;
+}
+
+GtkMenuItem *
+_gspell_context_menu_get_language_menu_item (const GspellLanguage            *current_language,
+                                            GspellLanguageActivatedCallback  callback,
+                                            gpointer                         user_data)
+{
+       GtkWidget *lang_menu;
+       GtkMenuItem *menu_item;
+
+       lang_menu = get_language_menu (current_language, callback, user_data);
+
+       menu_item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Language")));
+       gtk_menu_item_set_submenu (menu_item, lang_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
new file mode 100644
index 0000000..5359e15
--- /dev/null
+++ b/gspell/gspell-context-menu.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2016 - Sébastien Wilmet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GSPELL_CONTEXT_MENU_H
+#define GSPELL_CONTEXT_MENU_H
+
+#include <gtk/gtk.h>
+#include "gspell-language.h"
+
+G_BEGIN_DECLS
+
+typedef void (*GspellLanguageActivatedCallback) (const GspellLanguage *lang,
+                                                gpointer              user_data);
+
+G_GNUC_INTERNAL
+GtkMenuItem *  _gspell_context_menu_get_language_menu_item     (const GspellLanguage            
*current_language,
+                                                                GspellLanguageActivatedCallback  callback,
+                                                                gpointer                         user_data);
+
+G_END_DECLS
+
+#endif /* GSPELL_CONTEXT_MENU_H */
+
+/* ex:set ts=8 noet: */
diff --git a/gspell/gspell-text-view.c b/gspell/gspell-text-view.c
index be43af2..d2f4516 100644
--- a/gspell/gspell-text-view.c
+++ b/gspell/gspell-text-view.c
@@ -24,6 +24,7 @@
 #include "gspell-checker.h"
 #include "gspell-language.h"
 #include "gspell-text-buffer.h"
+#include "gspell-context-menu.h"
 
 /**
  * SECTION:text-view
@@ -73,8 +74,7 @@ enum
        PROP_ENABLE_LANGUAGE_MENU,
 };
 
-#define GSPELL_TEXT_VIEW_KEY   "gspell-text-view-key"
-#define LANGUAGE_KEY           "gspell-language-key"
+#define GSPELL_TEXT_VIEW_KEY "gspell-text-view-key"
 
 G_DEFINE_TYPE_WITH_PRIVATE (GspellTextView, gspell_text_view, G_TYPE_OBJECT)
 
@@ -133,22 +133,19 @@ notify_buffer_cb (GtkTextView    *gtk_view,
 }
 
 static void
-activate_language_cb (GtkWidget      *menu_item,
-                     GspellTextView *gspell_view)
+language_activated_cb (const GspellLanguage *lang,
+                      gpointer              user_data)
 {
+       GspellTextView *gspell_view;
        GspellTextViewPrivate *priv;
-       const GspellLanguage *lang;
        GtkTextBuffer *gtk_buffer;
        GspellTextBuffer *gspell_buffer;
        GspellChecker *checker;
 
-       priv = gspell_text_view_get_instance_private (gspell_view);
+       g_return_if_fail (GSPELL_IS_TEXT_VIEW (user_data));
 
-       lang = g_object_get_data (G_OBJECT (menu_item), LANGUAGE_KEY);
-       if (lang == NULL)
-       {
-               g_return_if_reached ();
-       }
+       gspell_view = GSPELL_TEXT_VIEW (user_data);
+       priv = gspell_text_view_get_instance_private (gspell_view);
 
        gtk_buffer = gtk_text_view_get_buffer (priv->view);
        gspell_buffer = gspell_text_buffer_get_from_gtk_text_buffer (gtk_buffer);
@@ -158,7 +155,7 @@ activate_language_cb (GtkWidget      *menu_item,
 }
 
 static const GspellLanguage *
-get_active_language (GspellTextView *gspell_view)
+get_current_language (GspellTextView *gspell_view)
 {
        GspellTextViewPrivate *priv;
        GtkTextBuffer *gtk_buffer;
@@ -179,65 +176,6 @@ get_active_language (GspellTextView *gspell_view)
        return gspell_checker_get_language (checker);
 }
 
-static GtkWidget *
-get_language_menu (GspellTextView *gspell_view)
-{
-       GtkWidget *menu;
-       const GspellLanguage *active_lang;
-       const GList *languages;
-       const GList *l;
-
-       menu = gtk_menu_new ();
-
-       active_lang = get_active_language (gspell_view);
-
-       languages = gspell_language_get_available ();
-       for (l = languages; l != NULL; l = l->next)
-       {
-               const GspellLanguage *lang = l->data;
-               const gchar *lang_name;
-               GtkWidget *menu_item;
-
-               lang_name = gspell_language_get_name (lang);
-
-               if (lang == active_lang)
-               {
-                       /* Do not create a group. Just mark the current language
-                        * as active.
-                        *
-                        * With a group, the first language in the list gets
-                        * activated, which changes the GspellChecker language
-                        * before we arrive to the active_lang.
-                        *
-                        * Also, having a bullet only for the active_lang is
-                        * sufficient (to be like in Firefox), the menu is
-                        * anyway ephemeral. No need to have an empty bullet for
-                        * all the other languages.
-                        */
-                       menu_item = gtk_radio_menu_item_new_with_label (NULL, lang_name);
-                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
-               }
-               else
-               {
-                       menu_item = gtk_menu_item_new_with_label (lang_name);
-               }
-
-               gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-
-               g_object_set_data (G_OBJECT (menu_item),
-                                  LANGUAGE_KEY,
-                                  (gpointer) lang);
-
-               g_signal_connect_object (menu_item,
-                                        "activate",
-                                        G_CALLBACK (activate_language_cb),
-                                        gspell_view,
-                                        0);
-       }
-
-       return menu;
-}
-
 static void
 populate_popup_cb (GtkTextView    *gtk_view,
                   GtkWidget      *popup,
@@ -269,12 +207,17 @@ populate_popup_cb (GtkTextView    *gtk_view,
 
        if (priv->enable_language_menu)
        {
+               const GspellLanguage *current_language;
+               GtkMenuItem *lang_menu_item;
+
+               current_language = get_current_language (gspell_view);
+               lang_menu_item = _gspell_context_menu_get_language_menu_item (current_language,
+                                                                             language_activated_cb,
+                                                                             gspell_view);
+
                /* Prepend language sub-menu */
-               menu_item = gtk_menu_item_new_with_mnemonic (_("_Language"));
-               gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
-               gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
-                                          get_language_menu (gspell_view));
-               gtk_widget_show_all (menu_item);
+               gtk_menu_shell_prepend (GTK_MENU_SHELL (menu),
+                                       GTK_WIDGET (lang_menu_item));
        }
 
        if (priv->inline_checker != NULL)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b8341c3..266b24d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,6 +1,7 @@
 # List of source files containing translatable strings.
 gspell/gspell-checker.c
 gspell/gspell-checker-dialog.c
+gspell/gspell-context-menu.c
 gspell/gspell-entry.c
 gspell/gspell-entry-buffer.c
 gspell/gspell-entry-utils.c


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