[Xfce4-commits] [apps/mousepad] 01/06: Move GSV language-related code to a new file

noreply at xfce.org noreply at xfce.org
Mon Jul 14 13:35:45 CEST 2014


This is an automated email from the git hooks/post-receive script.

mbrush pushed a commit to branch master
in repository apps/mousepad.

commit f113f6c88f191cbb7cd68493fa992cd111311b12
Author: Matthew Brush <mbrush at codebrainz.ca>
Date:   Sun Jul 13 23:21:58 2014 -0700

    Move GSV language-related code to a new file
    
    Re-write related code so that there's a single action group for the
    filetype languages that is shared between any menus to select the
    language. Add code to create the menus and use it for the main menu
    and the statusbar menu. This way when the language changes, it's
    reflected everywhere in the UI automatically.
---
 mousepad/Makefile.am          |    2 +
 mousepad/mousepad-languages.c |  512 +++++++++++++++++++++++++++++++++++++++++
 mousepad/mousepad-languages.h |   28 +++
 mousepad/mousepad-statusbar.c |   20 +-
 mousepad/mousepad-util.c      |   84 -------
 mousepad/mousepad-util.h      |    7 -
 mousepad/mousepad-window.c    |  375 ++++++------------------------
 7 files changed, 618 insertions(+), 410 deletions(-)

diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
index bb1f36a..15a8b7b 100644
--- a/mousepad/Makefile.am
+++ b/mousepad/Makefile.am
@@ -33,6 +33,8 @@ mousepad_SOURCES = \
 	mousepad-encoding-dialog.h \
 	mousepad-file.c \
 	mousepad-file.h \
+	mousepad-languages.c \
+	mousepad-languages.h \
 	mousepad-prefs-dialog.c \
 	mousepad-prefs-dialog.h \
 	mousepad-prefs-dialog-ui.h \
diff --git a/mousepad/mousepad-languages.c b/mousepad/mousepad-languages.c
new file mode 100644
index 0000000..650bea4
--- /dev/null
+++ b/mousepad/mousepad-languages.c
@@ -0,0 +1,512 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <mousepad/mousepad-languages.h>
+#include <mousepad/mousepad-util.h>
+#include <glib/gi18n.h>
+#include <gtksourceview/gtksourcelanguagemanager.h>
+
+
+
+static inline void
+mousepad_action_set_language (GtkAction *action,
+                              GtkSourceLanguage *language)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  if (GTK_IS_SOURCE_LANGUAGE (language))
+    {
+      g_object_set_data_full (G_OBJECT (action),
+                              "mousepad-language",
+                              g_object_ref (language),
+                              g_object_unref);
+    }
+  else
+    g_object_set_data (G_OBJECT (action), "mousepad-language", NULL);
+}
+
+
+
+static inline GtkSourceLanguage *
+mousepad_action_get_language (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return g_object_get_data (G_OBJECT (action), "mousepad-language");
+}
+
+
+
+static inline void
+mousepad_action_group_set_active_language (GtkActionGroup    *group,
+                                           GtkSourceLanguage *language)
+{
+  g_return_if_fail (GTK_IS_ACTION_GROUP (group));
+
+  if (GTK_IS_SOURCE_LANGUAGE (language))
+    {
+      g_object_set_data_full (G_OBJECT (group),
+                              "mousepad-active-language",
+                              g_object_ref (language),
+                              g_object_unref);
+    }
+  else
+    g_object_set_data (G_OBJECT (group), "mousepad-active-language", NULL);
+}
+
+
+
+static inline GtkSourceLanguage *
+mousepad_action_group_get_active_language (GtkActionGroup *group)
+{
+  g_return_val_if_fail (GTK_IS_ACTION_GROUP (group), NULL);
+
+  return g_object_get_data (G_OBJECT (group), "mousepad-active-language");
+}
+
+
+
+static GIcon *
+mousepad_languages_get_icon_for_mime_type (const gchar *mime_type)
+{
+  gchar *content_type;
+  GIcon *icon = NULL;
+
+  content_type = g_content_type_from_mime_type (mime_type);
+  if (content_type != NULL)
+    {
+      icon = g_content_type_get_icon (content_type);
+      g_free (content_type);
+    }
+
+  return icon;
+}
+
+
+
+static GIcon *
+mousepad_languages_get_icon_for_language (GtkSourceLanguage *language)
+{
+  gchar **mime_types;
+  GIcon  *mime_icon = NULL;
+
+  g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (language), NULL);
+
+  mime_types = gtk_source_language_get_mime_types (language);
+  if (G_LIKELY (mime_types != NULL && g_strv_length (mime_types)) > 0)
+    mime_icon = mousepad_languages_get_icon_for_mime_type (mime_types[0]);
+  g_strfreev (mime_types);
+
+  return mime_icon;
+}
+
+
+
+static void
+mousepad_languages_active_language_changed (GtkActionGroup  *group,
+                                            GtkToggleAction *action)
+{
+  GtkSourceLanguage *language;
+
+  if (gtk_toggle_action_get_active (action))
+    {
+      language = mousepad_action_get_language (GTK_ACTION (action));
+      mousepad_action_group_set_active_language (group, language);
+      g_signal_emit_by_name (group, "language-changed", language);
+    }
+}
+
+
+
+static GtkRadioAction *
+mousepad_languages_create_action (GtkActionGroup    *group,
+                                  GtkSourceLanguage *language,
+                                  GSList           **radio_action_group,
+                                  GtkAccelGroup     *accel_group)
+{
+  GtkRadioAction *action;
+  GQuark          value_quark;
+  GIcon          *icon = NULL;
+
+  g_return_val_if_fail (GTK_IS_ACTION_GROUP (group), NULL);
+  g_return_val_if_fail (language == NULL || GTK_IS_SOURCE_LANGUAGE (language), NULL);
+  g_return_val_if_fail (radio_action_group != NULL, NULL);
+
+  if (G_UNLIKELY (language == NULL))
+    {
+      /* NULL/'none' language is treated as plain text */
+      value_quark = g_quark_from_static_string ("mousepad-language-none");
+      action = gtk_radio_action_new ("mousepad-language-none", _("Plain Text"), _("No language"), NULL, value_quark);
+      gtk_action_set_accel_group (GTK_ACTION (action), accel_group);
+      mousepad_action_set_language (GTK_ACTION (action), NULL);
+      icon = mousepad_languages_get_icon_for_mime_type ("text/plain");
+    }
+  else
+    {
+      const gchar *language_id, *name;
+      gchar       *label, *tooltip;
+
+      language_id = gtk_source_language_get_id (language);
+      value_quark = g_quark_from_string (language_id);
+
+      /* the proper name of the language for user display */
+      name = gtk_source_language_get_name (language);
+
+      /* a label for the action in the action group */
+      label = g_strdup_printf ("mousepad-language-%s", language_id);
+
+      /* a tooltip to the section and name, ex. 'Scripts/Python' */
+      tooltip = g_strdup_printf ("%s/%s",
+                                 gtk_source_language_get_section (language),
+                                 gtk_source_language_get_name (language));
+
+      /* a unique id of the language, for the radio action's value */
+      value_quark = g_quark_from_string (language_id);
+
+      /* create the new action */
+      action = gtk_radio_action_new (label, name, tooltip, NULL, value_quark);
+      g_free (label);
+      g_free (tooltip);
+
+      gtk_action_set_accel_group (GTK_ACTION (action), accel_group);
+
+      /* update the action's related language */
+      mousepad_action_set_language (GTK_ACTION (action), language);
+
+      /* try and get an icon for the language's first mime-type if possible */
+      icon = mousepad_languages_get_icon_for_language (language);
+    }
+
+  /* set an icon for the action if we have one */
+  if (G_IS_ICON (icon))
+    {
+      gtk_action_set_gicon (GTK_ACTION (action), icon);
+      g_object_unref (icon);
+    }
+
+  /* watch for the 'none' language activation */
+  g_signal_connect_object (action,
+                           "activate",
+                           G_CALLBACK (mousepad_languages_active_language_changed),
+                           group,
+                           G_CONNECT_SWAPPED);
+
+  /* add it to the provided radio action group */
+  gtk_radio_action_set_group (action, *radio_action_group);
+  *radio_action_group = gtk_radio_action_get_group (action);
+
+  gtk_action_group_add_action_with_accel (group, GTK_ACTION (action), NULL);
+  g_object_unref (action);
+
+  return action;
+}
+
+
+
+GtkActionGroup *
+mousepad_languages_action_group_new (void)
+{
+  GtkSourceLanguageManager *manager;
+  const gchar       *const *language_ids;
+  const gchar       *const *language_id_ptr;
+  GSList                   *radio_action_group = NULL;
+  GtkActionGroup           *group;
+  GtkAccelGroup            *accel_group;
+  static gsize              installed_signal = 0;
+
+  /* one-time, add our 'language-changed' signal to the action group class */
+  if (g_once_init_enter (&installed_signal))
+    {
+      g_signal_new ("language-changed",
+                    GTK_TYPE_ACTION_GROUP,
+                    G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                    0, NULL, NULL,
+                    g_cclosure_marshal_VOID__OBJECT,
+                    G_TYPE_NONE, 1,
+                    GTK_TYPE_SOURCE_LANGUAGE);
+      g_once_init_leave (&installed_signal, 1);
+    }
+
+  accel_group = gtk_accel_group_new ();
+  group = gtk_action_group_new ("mousepad-languages");
+
+  /* add an action for the 'none' language */
+  mousepad_languages_create_action (group, NULL, &radio_action_group, accel_group);
+
+  /* the default is the 'none' language */
+  mousepad_action_group_set_active_language (group, NULL);
+
+  manager = gtk_source_language_manager_get_default ();
+  language_ids = gtk_source_language_manager_get_language_ids (manager);
+
+  for (language_id_ptr = language_ids; language_id_ptr && *language_id_ptr; language_id_ptr++)
+    {
+      GtkSourceLanguage *language;
+
+      /* lookup the language for the id */
+      language = gtk_source_language_manager_get_language (manager, *language_id_ptr);
+
+      /* create an action for the language */
+      mousepad_languages_create_action (group, language, &radio_action_group, accel_group);
+    }
+
+  g_object_unref (accel_group);
+
+  return group;
+}
+
+
+
+static GtkWidget *
+mousepad_languages_create_submenu (GtkActionGroup *group,
+                                   const gchar    *section)
+{
+  GtkWidget                *menu;
+  GtkWidget                *item;
+  GSList                   *language_ids, *iter;
+
+  menu = gtk_menu_new ();
+
+  language_ids = mousepad_languages_get_sorted_for_section (section);
+
+  for (iter = language_ids; iter != NULL; iter = g_slist_next (iter))
+    {
+      GtkAction         *action;
+      GtkSourceLanguage *language = iter->data;
+
+      action = mousepad_languages_get_action (group, language);
+      item = gtk_action_create_menu_item (action);
+
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+    }
+  g_slist_free (language_ids);
+
+  return menu;
+}
+
+
+
+GtkWidget *
+mousepad_languages_create_menu (GtkActionGroup *group)
+{
+  GtkWidget *menu;
+  GtkWidget *item;
+  GSList    *sections, *iter;
+  GtkAction *action;
+
+  menu = gtk_menu_new ();
+
+  /* add the 'none' language first */
+  action = gtk_action_group_get_action (group, "mousepad-language-none");
+  item = gtk_action_create_menu_item (action);
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show (item);
+
+  /* separator the 'none' language from the section submenus */
+  item = gtk_separator_menu_item_new ();
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show (item);
+
+  sections = mousepad_languages_get_sorted_sections ();
+  for (iter = sections; iter != NULL; iter = g_slist_next (iter))
+    {
+      const gchar *section = iter->data;
+      GtkWidget   *submenu;
+
+      /* create a menu item for the section */
+      item = gtk_menu_item_new_with_label (section);
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+      gtk_widget_show (item);
+
+      /* create a submenu for the section and it to the item */
+      submenu = mousepad_languages_create_submenu (group, section);
+      gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+
+    }
+  g_slist_free (sections);
+
+  return menu;
+}
+
+
+
+static GtkSourceLanguage *
+mousepad_languages_get_radio_action_group_active (GSList *actions)
+{
+  GSList *iter;
+
+  for (iter = actions; iter != NULL; iter = g_slist_next (iter))
+    {
+      if (gtk_toggle_action_get_active (iter->data))
+        return mousepad_action_get_language (iter->data);
+    }
+
+  return NULL;
+}
+
+
+
+GtkSourceLanguage *
+mousepad_languages_get_active (GtkActionGroup *group)
+{
+  GList             *actions, *action_iter;
+  GtkSourceLanguage *language = NULL;
+
+  /* scan for the first radio action in case there's other stuff in the group */
+  actions = gtk_action_group_list_actions (group);
+  for (action_iter = actions; action_iter != NULL; action_iter = g_list_next (action_iter))
+    {
+      /* make sure it's one of our language radio actions */
+      if (GTK_IS_RADIO_ACTION (action_iter->data) &&
+          GTK_IS_SOURCE_LANGUAGE (mousepad_action_get_language (action_iter->data)))
+        {
+          GSList *radio_actions;
+          /* get the active language from its group */
+          radio_actions = gtk_radio_action_get_group (action_iter->data);
+          language = mousepad_languages_get_radio_action_group_active (radio_actions);
+          break;
+        }
+    }
+  g_list_free (actions);
+
+  return language;
+}
+
+
+
+void
+mousepad_languages_set_active (GtkActionGroup    *group,
+                               GtkSourceLanguage *language)
+{
+  GtkAction *action;
+
+  g_return_if_fail (GTK_IS_ACTION_GROUP (group));
+
+  action = mousepad_languages_get_action (group, language);
+  if (G_UNLIKELY (action == NULL))
+    {
+      g_critical ("failed to find action for language '%s'",
+                  language ? gtk_source_language_get_id (language) : "none");
+      return;
+    }
+
+  /* the "language-changed" signal is emitted by the action groups handler
+   * for actions activating when we do this */
+  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+}
+
+
+
+GtkAction *
+mousepad_languages_get_action (GtkActionGroup    *group,
+                               GtkSourceLanguage *language)
+{
+  gchar       *action_name;
+  GtkAction   *action;
+  const gchar *language_id;
+
+  g_return_val_if_fail (GTK_IS_ACTION_GROUP (group), NULL);
+
+  if (GTK_IS_SOURCE_LANGUAGE (language))
+    language_id = gtk_source_language_get_id (language);
+  else
+    language_id = "none";
+
+  action_name = g_strdup_printf ("mousepad-language-%s", language_id);
+  action = gtk_action_group_get_action (group, action_name);
+  g_free (action_name);
+
+  return action;
+}
+
+
+
+GtkSourceLanguage *
+mousepad_languages_get_action_language (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return mousepad_action_get_language (action);
+}
+
+
+static gint
+mousepad_util_languages_name_compare (gconstpointer a,
+                                      gconstpointer b)
+{
+  const gchar *name_a, *name_b;
+
+  if (G_UNLIKELY (!GTK_IS_SOURCE_LANGUAGE (a)))
+    return -(a != b);
+  if (G_UNLIKELY (!GTK_IS_SOURCE_LANGUAGE (b)))
+    return a != b;
+
+  name_a = gtk_source_language_get_name (GTK_SOURCE_LANGUAGE (a));
+  name_b = gtk_source_language_get_name (GTK_SOURCE_LANGUAGE (b));
+
+  return g_utf8_collate (name_a, name_b);
+}
+
+
+
+GSList *
+mousepad_languages_get_sorted_sections (void)
+{
+  GSList                   *list = NULL;
+  const gchar *const       *languages;
+  GtkSourceLanguage        *language;
+  GtkSourceLanguageManager *manager;
+
+  manager = gtk_source_language_manager_get_default ();
+  languages = gtk_source_language_manager_get_language_ids (manager);
+
+  while (*languages)
+    {
+      language = gtk_source_language_manager_get_language (manager, *languages);
+      if (G_LIKELY (GTK_IS_SOURCE_LANGUAGE (language)))
+        {
+          /* ensure no duplicates in list */
+          if (!g_slist_find_custom (list,
+                                    gtk_source_language_get_section (language),
+                                    (GCompareFunc)g_strcmp0))
+            {
+              list = g_slist_prepend (list, (gchar *)gtk_source_language_get_section (language));
+            }
+        }
+      languages++;
+    }
+
+  return g_slist_sort (list, (GCompareFunc) g_utf8_collate);
+}
+
+
+
+GSList *
+mousepad_languages_get_sorted_for_section (const gchar *section)
+{
+  GSList                   *list = NULL;
+  const gchar *const       *languages;
+  GtkSourceLanguage        *language;
+  GtkSourceLanguageManager *manager;
+
+  g_return_val_if_fail (section != NULL, NULL);
+
+  manager = gtk_source_language_manager_get_default ();
+  languages = gtk_source_language_manager_get_language_ids (manager);
+
+  while (*languages)
+    {
+      language = gtk_source_language_manager_get_language (manager, *languages);
+      if (G_LIKELY (GTK_IS_SOURCE_LANGUAGE (language)))
+        {
+          /* only get languages in the specified section */
+          if (g_strcmp0 (gtk_source_language_get_section (language), section) == 0)
+            list = g_slist_prepend (list, language);
+        }
+      languages++;
+    }
+
+  return g_slist_sort(list, (GCompareFunc)mousepad_util_languages_name_compare);
+}
diff --git a/mousepad/mousepad-languages.h b/mousepad/mousepad-languages.h
new file mode 100644
index 0000000..fc801b0
--- /dev/null
+++ b/mousepad/mousepad-languages.h
@@ -0,0 +1,28 @@
+#ifndef MOUSEPAD_LANGUAGES_H_
+#define MOUSEPAD_LANGUAGES_H_ 1
+
+#include <gtksourceview/gtksourcelanguage.h>
+
+G_BEGIN_DECLS
+
+GtkActionGroup    *mousepad_languages_action_group_new     (void);
+
+GtkWidget         *mousepad_languages_create_menu          (GtkActionGroup    *group);
+
+GtkSourceLanguage *mousepad_languages_get_active           (GtkActionGroup    *group);
+
+void               mousepad_languages_set_active           (GtkActionGroup    *group,
+                                                            GtkSourceLanguage *language);
+
+GtkAction         *mousepad_languages_get_action           (GtkActionGroup    *group,
+                                                            GtkSourceLanguage *language);
+
+GtkSourceLanguage *mousepad_languages_get_action_language  (GtkAction         *action);
+
+GSList           *mousepad_languages_get_sorted_sections    (void);
+
+GSList           *mousepad_languages_get_sorted_for_section (const gchar      *section);
+
+G_END_DECLS
+
+#endif /* MOUSEPAD_LANGUAGES_H_ */
diff --git a/mousepad/mousepad-statusbar.c b/mousepad/mousepad-statusbar.c
index e4abdc0..84f722b 100644
--- a/mousepad/mousepad-statusbar.c
+++ b/mousepad/mousepad-statusbar.c
@@ -38,7 +38,7 @@ static gboolean mousepad_statusbar_filetype_clicked  (GtkWidget         *widget,
 enum
 {
   ENABLE_OVERWRITE,
-  POPULATE_FILETYPE_POPUP,
+  PROVIDE_LANGUAGES_MENU,
   LAST_SIGNAL,
 };
 
@@ -93,13 +93,13 @@ mousepad_statusbar_class_init (MousepadStatusbarClass *klass)
                   g_cclosure_marshal_VOID__BOOLEAN,
                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
-  statusbar_signals[POPULATE_FILETYPE_POPUP] =
-    g_signal_new (I_("populate-filetype-popup"),
+  statusbar_signals[PROVIDE_LANGUAGES_MENU] =
+    g_signal_new (I_("provide-languages-menu"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL,
-                  g_cclosure_marshal_VOID__OBJECT,
-                  G_TYPE_NONE, 1, GTK_TYPE_MENU);
+                  g_cclosure_marshal_generic,
+                  GTK_TYPE_MENU, 0);
 }
 
 
@@ -205,7 +205,7 @@ mousepad_statusbar_filetype_clicked (GtkWidget         *widget,
                                      GdkEventButton    *event,
                                      MousepadStatusbar *statusbar)
 {
-  GtkMenu *menu;
+  GtkMenu *menu = NULL;
   GList   *children;
   gint     n_children = 0;
 
@@ -215,11 +215,9 @@ mousepad_statusbar_filetype_clicked (GtkWidget         *widget,
   if (event->type != GDK_BUTTON_PRESS || event->button != 1)
     return FALSE;
 
-  /* create the popup menu */
-  menu = GTK_MENU (gtk_menu_new ());
-
-  /* send the signal to fill the menu */
-  g_signal_emit (G_OBJECT (statusbar), statusbar_signals[POPULATE_FILETYPE_POPUP], 0, menu);
+  /* get the window to create the popup menu for us */
+  g_signal_emit (statusbar, statusbar_signals[PROVIDE_LANGUAGES_MENU], 0, &menu);
+  g_warn_if_fail (GTK_IS_MENU (menu));
 
   /* get the number of items in the menu */
   children = gtk_container_get_children (GTK_CONTAINER (menu));
diff --git a/mousepad/mousepad-util.c b/mousepad/mousepad-util.c
index 9ca07a8..929d322 100644
--- a/mousepad/mousepad-util.c
+++ b/mousepad/mousepad-util.c
@@ -1135,90 +1135,6 @@ mousepad_util_color_schemes_get_sorted (void)
 
 
 
-/**
- * Language/filetype functions
- */
-gint
-mousepad_util_languages_name_compare (gconstpointer a,
-                                      gconstpointer b)
-{
-  const gchar *name_a, *name_b;
-
-  if (G_UNLIKELY (!GTK_IS_SOURCE_LANGUAGE (a)))
-    return -(a != b);
-  if (G_UNLIKELY (!GTK_IS_SOURCE_LANGUAGE (b)))
-    return a != b;
-
-  name_a = gtk_source_language_get_name (GTK_SOURCE_LANGUAGE (a));
-  name_b = gtk_source_language_get_name (GTK_SOURCE_LANGUAGE (b));
-
-  return g_utf8_collate (name_a, name_b);
-}
-
-
-
-GSList *
-mousepad_util_language_sections_get_sorted (void)
-{
-  GSList                   *list = NULL;
-  const gchar *const       *languages;
-  GtkSourceLanguage        *language;
-  GtkSourceLanguageManager *manager;
-
-  manager = gtk_source_language_manager_get_default ();
-  languages = gtk_source_language_manager_get_language_ids (manager);
-
-  while (*languages)
-    {
-      language = gtk_source_language_manager_get_language (manager, *languages);
-      if (G_LIKELY (GTK_IS_SOURCE_LANGUAGE (language)))
-        {
-          /* ensure no duplicates in list */
-          if (!g_slist_find_custom (list,
-                                    gtk_source_language_get_section (language),
-                                    (GCompareFunc)g_strcmp0))
-            {
-              list = g_slist_prepend (list, (gchar *)gtk_source_language_get_section (language));
-            }
-        }
-      languages++;
-    }
-
-  return g_slist_sort (list, (GCompareFunc)g_strcmp0);
-}
-
-
-
-GSList *
-mousepad_util_languages_get_sorted_for_section (const gchar *section)
-{
-  GSList                   *list = NULL;
-  const gchar *const       *languages;
-  GtkSourceLanguage        *language;
-  GtkSourceLanguageManager *manager;
-
-  mousepad_return_val_if_fail (section != NULL, NULL);
-
-  manager = gtk_source_language_manager_get_default ();
-  languages = gtk_source_language_manager_get_language_ids (manager);
-
-  while (*languages)
-    {
-      language = gtk_source_language_manager_get_language (manager, *languages);
-      if (G_LIKELY (GTK_IS_SOURCE_LANGUAGE (language)))
-        {
-          /* only get languages in the specified section */
-          if (g_strcmp0 (gtk_source_language_get_section (language), section) == 0)
-            list = g_slist_prepend (list, language);
-        }
-      languages++;
-    }
-
-  return g_slist_sort(list, (GCompareFunc)mousepad_util_languages_name_compare);
-}
-
-
-
 /* get the related action of the widget or walk up the parents to find one.
  * useful for example to get the related action of a tool item from its child. */
 GtkAction *
diff --git a/mousepad/mousepad-util.h b/mousepad/mousepad-util.h
index ef80c7d..2cfc9d6 100644
--- a/mousepad/mousepad-util.h
+++ b/mousepad/mousepad-util.h
@@ -126,13 +126,6 @@ GSList    *mousepad_util_color_schemes_get                (void);
 
 GSList    *mousepad_util_color_schemes_get_sorted         (void);
 
-gint       mousepad_util_languages_name_compare           (gconstpointer        a,
-                                                           gconstpointer        b);
-
-GSList    *mousepad_util_language_sections_get_sorted     (void);
-
-GSList    *mousepad_util_languages_get_sorted_for_section (const gchar         *section);
-
 GtkAction *mousepad_util_find_related_action              (GtkWidget           *widget);
 
 G_END_DECLS
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index ec213e8..0903515 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -44,6 +44,7 @@
 #include <mousepad/mousepad-search-bar.h>
 #include <mousepad/mousepad-statusbar.h>
 #include <mousepad/mousepad-print.h>
+#include <mousepad/mousepad-languages.h>
 #include <mousepad/mousepad-window.h>
 #include <mousepad/mousepad-window-ui.h>
 
@@ -104,12 +105,9 @@ static gboolean          mousepad_window_open_file                    (MousepadW
 static gboolean          mousepad_window_close_document               (MousepadWindow         *window,
                                                                        MousepadDocument       *document);
 static void              mousepad_window_set_title                    (MousepadWindow         *window);
-static void              mousepad_window_populate_statusbar_popup     (MousepadWindow         *window,
-                                                                       GtkMenu                *menu,
+static GtkMenu          *mousepad_window_provide_languages_menu       (MousepadWindow         *window,
                                                                        MousepadStatusbar      *statusbar);
 static void              mousepad_window_create_statusbar             (MousepadWindow         *window);
-static void              mousepad_window_statusbar_filetype_toggled   (GtkCheckMenuItem       *item,
-                                                                       MousepadWindow         *window);
 static gboolean          mousepad_window_get_in_fullscreen            (MousepadWindow         *window);
 static void              mousepad_window_update_main_widgets          (MousepadWindow         *window);
 
@@ -162,7 +160,7 @@ static void              mousepad_window_selection_changed            (MousepadD
 static void              mousepad_window_overwrite_changed            (MousepadDocument       *document,
                                                                        gboolean                overwrite,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_language_changed             (MousepadDocument       *document,
+static void              mousepad_window_buffer_language_changed      (MousepadDocument       *document,
                                                                        GtkSourceLanguage      *language,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_can_undo                     (MousepadWindow         *window,
@@ -193,7 +191,6 @@ static void              mousepad_window_update_tabs                  (MousepadW
                                                                        gchar                  *key,
                                                                        GSettings              *settings);
 static void              mousepad_window_menu_color_schemes           (MousepadWindow         *window);
-static void              mousepad_window_menu_languages               (MousepadWindow         *window);
 
 /* recent functions */
 static void              mousepad_window_recent_add                   (MousepadWindow         *window,
@@ -343,8 +340,6 @@ static void              mousepad_window_action_statusbar             (GtkToggle
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_fullscreen            (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_language              (GtkToggleAction        *action,
-                                                                       MousepadWindow         *window);
 static void              mousepad_window_action_auto_indent           (GtkToggleAction        *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_line_ending           (GtkRadioAction         *action,
@@ -383,8 +378,9 @@ struct _MousepadWindow
   /* the current active document */
   MousepadDocument    *active;
 
-  /* action group */
+  /* action groups */
   GtkActionGroup      *action_group;
+  GtkActionGroup      *language_actions;
 
   /* recent manager */
   GtkRecentManager    *recent_manager;
@@ -685,6 +681,42 @@ mousepad_window_restore (MousepadWindow *window)
 
 
 static void
+mousepad_window_language_changed (MousepadWindow    *window,
+                                  GtkSourceLanguage *language,
+                                  GtkActionGroup    *group)
+{
+  /* update the language on the active file */
+  mousepad_file_set_language (window->active->file, language);
+
+  /* update the filetype shown in the statusbar */
+  mousepad_statusbar_set_language (MOUSEPAD_STATUSBAR (window->statusbar), language);
+}
+
+
+
+static void
+mousepad_window_create_languages_menu (MousepadWindow *window)
+{
+  GtkWidget *menu, *item;
+
+  /* create the languages menu and add it to the placeholder */
+  menu = mousepad_languages_create_menu (window->language_actions);
+  item = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu/document-menu/language-menu");
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
+  gtk_widget_show_all (menu);
+  gtk_widget_show (item);
+
+  /* watch for activations of the language actions */
+  g_signal_connect_object (window->language_actions,
+                           "language-changed",
+                           G_CALLBACK (mousepad_window_language_changed),
+                           window,
+                           G_CONNECT_SWAPPED);
+}
+
+
+
+static void
 mousepad_window_create_menubar (MousepadWindow *window)
 {
   GtkAction *action;
@@ -693,6 +725,8 @@ mousepad_window_create_menubar (MousepadWindow *window)
   window->menubar = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu");
   gtk_box_pack_start (GTK_BOX (window->box), window->menubar, FALSE, FALSE, 0);
 
+  mousepad_window_create_languages_menu (window);
+
   /* sync the menubar visibility and action state to the setting */
   action = gtk_action_group_get_action (window->action_group, "menubar");
   if (MOUSEPAD_SETTING_GET_BOOLEAN (WINDOW_FULLSCREEN))
@@ -875,8 +909,8 @@ mousepad_window_create_statusbar (MousepadWindow *window)
                             G_CALLBACK (mousepad_window_action_statusbar_overwrite), window);
 
   /* populate filetype popup menu signal */
-  g_signal_connect_swapped (G_OBJECT (window->statusbar), "populate-filetype-popup",
-                            G_CALLBACK (mousepad_window_populate_statusbar_popup), window);
+  g_signal_connect_swapped (G_OBJECT (window->statusbar), "provide-languages-menu",
+                            G_CALLBACK (mousepad_window_provide_languages_menu), window);
 
   /* update the statusbar items */
   if (MOUSEPAD_IS_DOCUMENT (window->active))
@@ -940,11 +974,15 @@ mousepad_window_init (MousepadWindow *window)
   gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
   gtk_action_group_add_radio_actions (window->action_group, radio_action_entries, G_N_ELEMENTS (radio_action_entries), -1, G_CALLBACK (mousepad_window_action_line_ending), GTK_WIDGET (window));
 
+  /* the action group for the languages/filetypes actions */
+  window->language_actions = mousepad_languages_action_group_new ();
+
   /* create the ui manager and connect proxy signals for the statusbar */
   window->ui_manager = gtk_ui_manager_new ();
   g_signal_connect (G_OBJECT (window->ui_manager), "connect-proxy", G_CALLBACK (mousepad_window_connect_proxy), window);
   g_signal_connect (G_OBJECT (window->ui_manager), "disconnect-proxy", G_CALLBACK (mousepad_window_disconnect_proxy), window);
   gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0);
+  gtk_ui_manager_insert_action_group (window->ui_manager, window->language_actions, 1);
   gtk_ui_manager_add_ui_from_string (window->ui_manager, mousepad_window_ui, mousepad_window_ui_length, NULL);
 
   /* build the templates menu when the item is shown for the first time */
@@ -958,9 +996,6 @@ mousepad_window_init (MousepadWindow *window)
   /* add color schemes menu */
   mousepad_window_menu_color_schemes (window);
 
-  /* add languages/filetypes menu */
-  mousepad_window_menu_languages (window);
-
   /* set accel group for the window */
   accel_group = gtk_ui_manager_get_accel_group (window->ui_manager);
   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
@@ -1058,8 +1093,9 @@ mousepad_window_finalize (GObject *object)
   g_signal_handlers_disconnect_matched (G_OBJECT (window->ui_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
   g_object_unref (G_OBJECT (window->ui_manager));
 
-  /* release the action group */
+  /* release the action groups */
   g_object_unref (G_OBJECT (window->action_group));
+  g_object_unref (G_OBJECT (window->language_actions));
 
   /* free clipboard history if needed */
   if (clipboard_history_ref_count == 0 && clipboard_history != NULL)
@@ -1657,92 +1693,12 @@ mousepad_window_set_title (MousepadWindow *window)
 
 
 
-static void
-mousepad_window_statusbar_filetype_toggled (GtkCheckMenuItem *item,
-                                            MousepadWindow   *window)
+/* give the statusbar a languages menu created from our action group */
+static GtkMenu *
+mousepad_window_provide_languages_menu (MousepadWindow    *window,
+                                        MousepadStatusbar *statusbar)
 {
-  const gchar              *language_id;
-  GtkSourceLanguage        *language;
-  GtkSourceLanguageManager *manager;
-
-  mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
-  mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
-
-  manager = gtk_source_language_manager_get_default ();
-  language_id = g_object_get_data (G_OBJECT (item), "language_id");
-
-  /* check if None was selected */
-  if (!language_id || g_strcmp0 (language_id, "none") == 0)
-    {
-      gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (window->active->buffer), NULL);
-      gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (window->active->buffer), FALSE);
-      return;
-    }
-
-  /* set to a non-None language */
-  language = gtk_source_language_manager_get_language (manager, language_id);
-  gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (window->active->buffer), TRUE);
-  gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (window->active->buffer), language);
-}
-
-
-
-static void
-mousepad_window_populate_statusbar_popup (MousepadWindow    *window,
-                                          GtkMenu           *menu,
-                                          MousepadStatusbar *statusbar)
-{
-  GSList            *group = NULL;
-  GSList            *sections, *s_iter;
-  GSList            *languages, *l_iter;
-  GtkWidget         *item;
-  GtkWidget         *submenu;
-  GtkSourceLanguage *active;
-
-  mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
-  mousepad_return_if_fail (MOUSEPAD_IS_DOCUMENT (window->active));
-
-  active = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (window->active->buffer));
-
-  item = gtk_radio_menu_item_new_with_label (group, _("None"));
-  group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
-  g_object_set_data (G_OBJECT (item), "language_id", "none");
-  g_signal_connect (item, "toggled", G_CALLBACK (mousepad_window_statusbar_filetype_toggled), window);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show (item);
-
-  if (!active)
-    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
-
-  item = gtk_separator_menu_item_new ();
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show (item);
-
-  sections = mousepad_util_language_sections_get_sorted ();
-
-  for (s_iter = sections ; s_iter != NULL; s_iter = g_slist_next (s_iter))
-    {
-      item = gtk_menu_item_new_with_label (s_iter->data);
-      gtk_widget_show (item);
-      submenu = gtk_menu_new ();
-      gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
-      gtk_widget_show (submenu);
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-
-      languages = mousepad_util_languages_get_sorted_for_section (s_iter->data);
-      for (l_iter = languages; l_iter != NULL; l_iter = g_slist_next (l_iter))
-        {
-          item = gtk_radio_menu_item_new_with_label (group, gtk_source_language_get_name (l_iter->data));
-          group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
-          g_object_set_data (G_OBJECT (item), "language_id", (gpointer) gtk_source_language_get_id (l_iter->data));
-          g_signal_connect (item, "toggled", G_CALLBACK (mousepad_window_statusbar_filetype_toggled), window);
-          gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
-          gtk_widget_show (item);
-
-          if (active == l_iter->data)
-            gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
-        }
-    }
+  return GTK_MENU (mousepad_languages_create_menu (window->language_actions));
 }
 
 
@@ -1829,7 +1785,7 @@ mousepad_window_notebook_added (GtkNotebook     *notebook,
   g_signal_connect (G_OBJECT (page), "cursor-changed", G_CALLBACK (mousepad_window_cursor_changed), window);
   g_signal_connect (G_OBJECT (page), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
   g_signal_connect (G_OBJECT (page), "overwrite-changed", G_CALLBACK (mousepad_window_overwrite_changed), window);
-  g_signal_connect (G_OBJECT (page), "language-changed", G_CALLBACK (mousepad_window_language_changed), window);
+  g_signal_connect (G_OBJECT (page), "language-changed", G_CALLBACK (mousepad_window_buffer_language_changed), window);
   g_signal_connect (G_OBJECT (page), "drag-data-received", G_CALLBACK (mousepad_window_drag_data_received), window);
   g_signal_connect_swapped (G_OBJECT (document->buffer), "notify::can-undo", G_CALLBACK (mousepad_window_can_undo), window);
   g_signal_connect_swapped (G_OBJECT (document->buffer), "notify::can-redo", G_CALLBACK (mousepad_window_can_redo), window);
@@ -2131,41 +2087,12 @@ mousepad_window_overwrite_changed (MousepadDocument *document,
 
 
 static void
-mousepad_window_language_changed (MousepadDocument  *document,
-                                  GtkSourceLanguage *language,
-                                  MousepadWindow    *window)
+mousepad_window_buffer_language_changed (MousepadDocument  *document,
+                                         GtkSourceLanguage *language,
+                                         MousepadWindow    *window)
 {
-  gchar     *path;
-  GtkWidget *item;
-
-  if (!GTK_IS_SOURCE_LANGUAGE (language))
-    goto set_none;
-
-  path = g_strdup_printf ("/main-menu/document-menu/language-menu/"
-                          "placeholder-language-section-items/"
-                          "language-section-%s/language-%s",
-                          gtk_source_language_get_section (language),
-                          gtk_source_language_get_id (language));
-  item = gtk_ui_manager_get_widget (window->ui_manager, path);
-  g_free (path);
-
-  /* activate the appropriate menu item for the new language */
-  if (GTK_IS_CHECK_MENU_ITEM (item))
-    {
-      gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
-      goto set_statusbar;
-    }
-
-set_none:
-  item = gtk_ui_manager_get_widget (window->ui_manager,
-                                        "/main-menu/document-menu/language-menu/language-none");
-  if (GTK_IS_CHECK_MENU_ITEM (item))
-    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
-
-set_statusbar:
-  /* set the filetype in the statusbar */
-  if (window->statusbar)
-    mousepad_statusbar_set_language (MOUSEPAD_STATUSBAR (window->statusbar), language);
+  /* activate the action for the new buffer language */
+  mousepad_languages_set_active (window->language_actions, language);
 }
 
 
@@ -2563,6 +2490,7 @@ mousepad_window_update_actions (MousepadWindow *window)
   gboolean            active, sensitive;
   MousepadLineEnding  line_ending;
   const gchar        *action_name;
+  GtkSourceLanguage  *language;
 
   mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
 
@@ -2643,6 +2571,10 @@ mousepad_window_update_actions (MousepadWindow *window)
       if (G_LIKELY (action != NULL))
         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
 
+      /* update the currently active language */
+      language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (window->active->buffer));
+      mousepad_languages_set_active (window->language_actions, language);
+
       /* allow menu actions again */
       lock_menu_updates--;
     }
@@ -3637,143 +3569,6 @@ mousepad_window_menu_color_schemes (MousepadWindow *window)
 
 
 
-static void
-mousepad_window_menu_languages (MousepadWindow *window)
-{
-  gint                  merge_id;
-  gchar                *name, *section_path;
-  gchar                 section_name[64];
-  GtkAction            *action;
-  GtkRadioAction       *radio_action;
-  GSList               *group = NULL;
-  GSList               *sections, *sect_iter, *languages, *lang_iter;
-
-  lock_menu_updates++;
-
-  merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
-
-  /* add the none language directly under the filetype */
-  radio_action = gtk_radio_action_new ("language-none",
-                                 _("None"),
-                                 _("No filetype"),
-                                 NULL,
-                                 g_str_hash ("none"));
-  gtk_radio_action_set_group (radio_action, group);
-  group = gtk_radio_action_get_group (radio_action);
-  g_signal_connect (G_OBJECT (radio_action), "activate", G_CALLBACK (mousepad_window_action_language), window);
-  gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (radio_action), "");
-
-  /* release the action */
-  g_object_unref (G_OBJECT (radio_action));
-
-  /* add the action to the go menu */
-  gtk_ui_manager_add_ui (window->ui_manager,
-                         merge_id,
-                         "/main-menu/document-menu/language-menu/placeholder-language-section-items",
-                         "language-none",
-                         "language-none",
-                         GTK_UI_MANAGER_MENUITEM,
-                         FALSE);
-
-  /* add a separator */
-  gtk_ui_manager_add_ui (window->ui_manager,
-                         merge_id,
-                         "/main-menu/document-menu/language-menu/placeholder-language-section-items",
-                         "language-separator",
-                         NULL,
-                         GTK_UI_MANAGER_SEPARATOR,
-                         FALSE);
-
-  sections = mousepad_util_language_sections_get_sorted ();
-
-  for (sect_iter = sections; sect_iter != NULL; sect_iter = g_slist_next (sect_iter))
-    {
-      languages = mousepad_util_languages_get_sorted_for_section (sect_iter->data);
-
-      /* make sure there are langs in the section, otherwise skip it */
-      if (!languages)
-        continue;
-      else if (!g_slist_length (languages))
-        {
-          g_slist_free (languages);
-          continue;
-        }
-
-      g_snprintf (section_name, 64, "language-section-%s", (gchar *)sect_iter->data);
-
-      /* add the section directly under the gtkuimanager dynamic menu filetype */
-      action = gtk_action_new (section_name,
-                               sect_iter->data,
-                               NULL,
-                               NULL);
-      gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (action), "");
-
-      /* release the action */
-      g_object_unref (G_OBJECT (action));
-
-      /* add a menu for each section */
-      gtk_ui_manager_add_ui (window->ui_manager,
-                             merge_id,
-                             "/main-menu/document-menu/language-menu/placeholder-language-section-items",
-                             section_name,
-                             section_name,
-                             GTK_UI_MANAGER_MENU,
-                             FALSE);
-
-      section_path = g_strdup_printf ("/main-menu/document-menu/language-menu/"
-                                      "placeholder-language-section-items/%s",
-                                      section_name);
-
-      for (lang_iter = languages; lang_iter != NULL; lang_iter = g_slist_next (lang_iter))
-        {
-          if (g_strcmp0 (sect_iter->data, gtk_source_language_get_section (lang_iter->data)) == 0)
-          {
-            /* create action name */
-            name = g_strdup_printf ("language-%s", gtk_source_language_get_id (lang_iter->data));
-
-            radio_action = gtk_radio_action_new (name,
-                                                 gtk_source_language_get_name (lang_iter->data),
-                                                 NULL,
-                                                 NULL,
-                                                 g_str_hash (gtk_source_language_get_id (lang_iter->data)));
-            gtk_radio_action_set_group (radio_action, group);
-            group = gtk_radio_action_get_group (radio_action);
-            g_signal_connect (G_OBJECT (radio_action),
-                              "activate",
-                              G_CALLBACK (mousepad_window_action_language),
-                              window);
-            gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (radio_action), "");
-
-            /* release the action */
-            g_object_unref (G_OBJECT (radio_action));
-
-            /* add the action to the section menu */
-            gtk_ui_manager_add_ui (window->ui_manager,
-                                   merge_id,
-                                   section_path,
-                                   name,
-                                   name,
-                                   GTK_UI_MANAGER_MENUITEM,
-                                   FALSE);
-
-            /* cleanup before next language */
-            g_free (name);
-          }
-        }
-
-        /* cleanup before next section */
-        g_free (section_path);
-        g_slist_free (languages);
-    }
-
-  g_slist_free (sections);
-
-  /* unlock */
-  lock_menu_updates--;
-}
-
-
-
 /**
  * Menu Actions
  *
@@ -5233,42 +5028,6 @@ mousepad_window_action_fullscreen (GtkToggleAction *action,
 
 
 static void
-mousepad_window_action_language (GtkToggleAction *action,
-                                 MousepadWindow  *window)
-{
-  guint                     lang_hash;
-  const gchar *const       *lang_id;
-  GtkSourceLanguage        *language;
-  GtkSourceLanguageManager *manager;
-  GtkSourceBuffer          *buffer;
-
-  lang_hash = (guint) gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
-  buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (window->active->textview)));
-
-  if (lang_hash == g_str_hash ("none"))
-    {
-      gtk_source_buffer_set_language (buffer, NULL);
-      return;
-    }
-
-  manager = gtk_source_language_manager_get_default ();
-  lang_id = gtk_source_language_manager_get_language_ids (manager);
-
-  while (*lang_id)
-    {
-      if (g_str_hash (*lang_id) == lang_hash)
-        {
-          language = gtk_source_language_manager_get_language (manager, *lang_id);
-          gtk_source_buffer_set_language (buffer, language);
-          break;
-        }
-      lang_id++;
-    }
-}
-
-
-
-static void
 mousepad_window_action_auto_indent (GtkToggleAction *action,
                                     MousepadWindow  *window)
 {

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list