[gnome-builder/wip/slaf/spellcheck-sidebar: 22/33] spellchecker: add a language's button class using a popover



commit 05ee77f59e31810d3aecd0a291a188051c05313e
Author: Sébastien Lafargue <slafargue gnome org>
Date:   Tue Jan 10 19:26:35 2017 +0100

    spellchecker: add a language's button class using a popover

 libide/Makefile.am                                |    2 +
 libide/editor/ide-editor-spell-language-popover.c |  394 +++++++++++++++++++++
 libide/editor/ide-editor-spell-language-popover.h |   36 ++
 3 files changed, 432 insertions(+), 0 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 2e607bd..592bbaa 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -394,6 +394,8 @@ libide_1_0_la_SOURCES =                                   \
        editor/ide-editor-spell-utils.h                   \
        editor/ide-editor-spell-dict.c                    \
        editor/ide-editor-spell-dict.h                    \
+       editor/ide-editor-spell-language-popover.c        \
+       editor/ide-editor-spell-language-popover.h        \
        editor/ide-editor-spell-widget.c                  \
        editor/ide-editor-spell-widget.h                  \
        editor/ide-editor-tweak-widget.c                  \
diff --git a/libide/editor/ide-editor-spell-language-popover.c 
b/libide/editor/ide-editor-spell-language-popover.c
new file mode 100644
index 0000000..3f92cc7
--- /dev/null
+++ b/libide/editor/ide-editor-spell-language-popover.c
@@ -0,0 +1,394 @@
+/* ide-editor-spell-language-popover.c
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Adaptation of GspellLanguageChooserButton to show a popover
+ * https://wiki.gnome.org/Projects/gspell
+ */
+
+#include "ide-editor-spell-language-popover.h"
+
+#include <glib/gi18n.h>
+#include <pnl.h>
+
+#include "util/ide-gtk.h"
+#include "workbench/ide-workbench.h"
+
+struct _IdeEditorSpellLanguagePopover
+{
+  GtkButton             parent_instance;
+
+  IdePerspective       *editor;
+  GtkPopover           *popover;
+  GtkTreeView          *treeview;
+  GtkTreeSelection     *selection;
+  GtkTreeStore         *store;
+  GtkScrolledWindow    *scrolled_window;
+  const GspellLanguage *language;
+
+  gint                  edge_side;
+  guint                 default_language : 1;
+};
+
+static void ide_editor_spell_language_popover_language_chooser_iface_init (GspellLanguageChooserInterface 
*iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeEditorSpellLanguagePopover, ide_editor_spell_language_popover, GTK_TYPE_BUTTON,
+                         G_IMPLEMENT_INTERFACE (GSPELL_TYPE_LANGUAGE_CHOOSER, 
ide_editor_spell_language_popover_language_chooser_iface_init))
+
+enum {
+  PROP_0,
+  PROP_LANGUAGE,
+  PROP_LANGUAGE_CODE,
+  N_PROPS
+};
+
+enum
+{
+  COLUMN_LANGUAGE_NAME,
+  COLUMN_LANGUAGE_POINTER,
+  N_COLUMNS
+};
+
+IdeEditorSpellLanguagePopover *
+ide_editor_spell_language_popover_new (const GspellLanguage *current_language)
+{
+  return g_object_new (IDE_TYPE_EDITOR_SPELL_LANGUAGE_POPOVER,
+                       "language", current_language,
+                       NULL);
+}
+
+static void
+scroll_to_selected (IdeEditorSpellLanguagePopover *self)
+{
+  GtkTreeIter iter;
+  GtkTreePath *path;
+
+  if (gtk_tree_selection_get_selected (self->selection, NULL, &iter) &&
+      NULL != (path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->store), &iter)))
+    {
+      gtk_tree_view_scroll_to_cell (self->treeview, path, NULL, TRUE, .5, 0.0);
+      gtk_tree_path_free (path);
+    }
+}
+
+static void
+populate_popover (IdeEditorSpellLanguagePopover *self)
+{
+  const GList *available_langs;
+  const gchar *name;
+  GtkTreeIter iter;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  available_langs = gspell_language_get_available ();
+  for (const GList *l = available_langs; l != NULL; l = l->next)
+    {
+      name = gspell_language_get_name (l->data);
+      gtk_list_store_append (GTK_LIST_STORE (self->store), &iter);
+      gtk_list_store_set (GTK_LIST_STORE (self->store), &iter,
+                          COLUMN_LANGUAGE_NAME, name,
+                          COLUMN_LANGUAGE_POINTER, l->data,
+                          -1);
+    }
+}
+
+static void
+ide_editor_spell_language_popover_treeview_row_activated_cb (IdeEditorSpellLanguagePopover *self,
+                                                             GtkTreePath                   *path,
+                                                             GtkTreeViewColumn             *column,
+                                                             GtkTreeView                   *treeview)
+{
+  GspellLanguage *lang;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+  g_assert (GTK_IS_TREE_VIEW (treeview));
+
+  if (gtk_tree_selection_get_selected (self->selection, &model, &iter))
+    {
+      gtk_tree_model_get (model, &iter, COLUMN_LANGUAGE_POINTER, &lang, -1);
+      gspell_language_chooser_set_language (GSPELL_LANGUAGE_CHOOSER (self), lang);
+      gtk_popover_popdown (self->popover);
+    }
+}
+
+static GtkPopover *
+create_popover (IdeEditorSpellLanguagePopover *self)
+{
+  GtkPopover *popover;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  self->treeview = g_object_new (GTK_TYPE_TREE_VIEW,
+                                 "headers-visible", FALSE,
+                                 "visible", TRUE,
+                                 "expand", TRUE,
+                                 NULL);
+
+  self->selection = gtk_tree_view_get_selection (self->treeview);
+  gtk_tree_selection_set_mode (self->selection, GTK_SELECTION_BROWSE);
+
+  self->store = GTK_TREE_STORE (gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GSPELL_TYPE_LANGUAGE));
+  gtk_tree_view_set_model (self->treeview, GTK_TREE_MODEL (self->store));
+  gtk_tree_view_insert_column_with_attributes (self->treeview, -1, NULL,
+                                               gtk_cell_renderer_text_new (),
+                                               "text", COLUMN_LANGUAGE_NAME,
+                                               NULL);
+
+  self->scrolled_window = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
+                                        "visible", TRUE,
+                                        "expand", TRUE,
+                                        "hscrollbar-policy", GTK_POLICY_NEVER,
+                                        "max-content-height", 400,
+                                        "propagate-natural-height", TRUE,
+                                        NULL);
+  popover = g_object_new (GTK_TYPE_POPOVER,
+                          "relative-to", self,
+                          "position", GTK_POS_TOP,
+                          NULL);
+
+  gtk_container_add (GTK_CONTAINER (self->scrolled_window), GTK_WIDGET (self->treeview));
+  gtk_container_add (GTK_CONTAINER (popover), GTK_WIDGET (self->scrolled_window));
+
+  g_signal_connect_object (self->treeview,
+                           "row-activated",
+                           G_CALLBACK (ide_editor_spell_language_popover_treeview_row_activated_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  return popover;
+}
+
+static void
+select_language (IdeEditorSpellLanguagePopover *self,
+                 const GspellLanguage          *language)
+{
+  GtkTreeModel *model = (GtkTreeModel *)self->store;
+  const GspellLanguage *lang;
+  GtkTreeIter iter;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  if (self->treeview == NULL ||
+      lang == NULL ||
+      !gtk_tree_model_get_iter_first (model, &iter))
+    return;
+
+  g_assert (GTK_IS_TREE_VIEW (self->treeview));
+  g_assert (GTK_IS_TREE_MODEL (self->store));
+
+  do
+    {
+      gtk_tree_model_get (model, &iter, COLUMN_LANGUAGE_POINTER, &lang, -1);
+      if (self->language == lang)
+        gtk_tree_selection_select_iter (self->selection, &iter);
+    }
+  while (gtk_tree_model_iter_next (model, &iter));
+}
+
+static void
+ide_editor_spell_language_popover_button_clicked (GtkButton *button)
+{
+  IdeEditorSpellLanguagePopover *self = (IdeEditorSpellLanguagePopover *)button;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  gspell_language_chooser_set_language (GSPELL_LANGUAGE_CHOOSER (self),
+                                        self->default_language ? NULL : self->language);
+
+  if (self->popover == NULL)
+    {
+      self->popover = g_object_ref (create_popover (self));
+      populate_popover (self);
+    }
+
+  gtk_popover_popup (self->popover);
+  select_language (self, self->language);
+  scroll_to_selected (self);
+}
+
+static void
+update_button_label (IdeEditorSpellLanguagePopover *self)
+{
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  if (self->language != NULL)
+    gtk_button_set_label (GTK_BUTTON (self), gspell_language_get_name (self->language));
+  else
+    gtk_button_set_label (GTK_BUTTON (self), _("No language selected"));
+}
+
+static void
+ide_editor_spell_language_popover_set_language (GspellLanguageChooser *chooser,
+                                                const GspellLanguage  *language)
+{
+  IdeEditorSpellLanguagePopover *self = (IdeEditorSpellLanguagePopover *)chooser;
+  gboolean notify_language_code = FALSE;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  if (self->default_language != (language == NULL))
+    {
+      self->default_language = (language == NULL);
+      notify_language_code = TRUE;
+    }
+
+  if (language == NULL && NULL == (language = gspell_language_get_default ()) && self->selection != NULL)
+    gtk_tree_selection_unselect_all (self->selection);
+
+  if (self->language != language)
+    {
+      self->language = language;
+      update_button_label (self);
+
+      g_object_notify (G_OBJECT (chooser), "language");
+      notify_language_code = TRUE;
+    }
+
+  if (notify_language_code)
+    g_object_notify (G_OBJECT (chooser), "language-code");
+
+  select_language (self, self->language);
+}
+
+static const GspellLanguage *
+ide_editor_spell_language_popover_get_language_full (GspellLanguageChooser *chooser,
+                                                     gboolean              *default_language)
+{
+  IdeEditorSpellLanguagePopover *self = (IdeEditorSpellLanguagePopover *)chooser;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  if (default_language != NULL)
+    *default_language = self->default_language;
+
+  return self->language;
+}
+
+static void
+ide_editor_spell_language_popover_finalize (GObject *object)
+{
+  IdeEditorSpellLanguagePopover *self = (IdeEditorSpellLanguagePopover *)object;
+
+  g_assert (IDE_IS_EDITOR_SPELL_LANGUAGE_POPOVER (self));
+
+  g_clear_object (&self->popover);
+}
+
+static void
+ide_editor_spell_language_popover_get_property (GObject    *object,
+                                                guint       prop_id,
+                                                GValue     *value,
+                                                GParamSpec *pspec)
+{
+  GspellLanguageChooser *chooser = GSPELL_LANGUAGE_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_LANGUAGE:
+      g_value_set_boxed (value, gspell_language_chooser_get_language (chooser));
+      break;
+
+    case PROP_LANGUAGE_CODE:
+      g_value_set_string (value, gspell_language_chooser_get_language_code (chooser));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_editor_spell_language_popover_set_property (GObject      *object,
+                                                guint         prop_id,
+                                                const GValue *value,
+                                                GParamSpec   *pspec)
+{
+  GspellLanguageChooser *chooser = GSPELL_LANGUAGE_CHOOSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_LANGUAGE:
+      gspell_language_chooser_set_language (chooser, g_value_get_boxed (value));
+      break;
+
+    case PROP_LANGUAGE_CODE:
+      gspell_language_chooser_set_language_code (chooser, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_editor_spell_language_popover_constructed (GObject *object)
+{
+  G_OBJECT_CLASS (ide_editor_spell_language_popover_parent_class)->constructed (object);
+
+  update_button_label (IDE_EDITOR_SPELL_LANGUAGE_POPOVER (object));
+}
+
+static void
+ide_editor_spell_language_popover_map (GtkWidget *widget)
+{
+  IdeEditorSpellLanguagePopover *self = (IdeEditorSpellLanguagePopover *)widget;
+  IdeWorkbench *workbench;
+  GtkWidget *edge;
+
+  GTK_WIDGET_CLASS (ide_editor_spell_language_popover_parent_class)->map (widget);
+
+  workbench = ide_widget_get_workbench (widget);
+  g_assert (IDE_IS_WORKBENCH (workbench));
+
+  if (NULL != (edge = gtk_widget_get_ancestor (widget, PNL_TYPE_DOCK_OVERLAY_EDGE)))
+    self->edge_side = pnl_dock_overlay_edge_get_edge (PNL_DOCK_OVERLAY_EDGE (edge));
+
+  self->editor = ide_workbench_get_perspective_by_name (workbench, "editor");
+}
+
+static void
+ide_editor_spell_language_popover_class_init (IdeEditorSpellLanguagePopoverClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+  object_class->finalize = ide_editor_spell_language_popover_finalize;
+  object_class->get_property = ide_editor_spell_language_popover_get_property;
+  object_class->set_property = ide_editor_spell_language_popover_set_property;
+  object_class->constructed = ide_editor_spell_language_popover_constructed;
+
+  widget_class->map = ide_editor_spell_language_popover_map;
+  button_class->clicked = ide_editor_spell_language_popover_button_clicked;
+
+  g_object_class_override_property (object_class, PROP_LANGUAGE, "language");
+  g_object_class_override_property (object_class, PROP_LANGUAGE_CODE, "language-code");
+}
+
+static void
+ide_editor_spell_language_popover_init (IdeEditorSpellLanguagePopover *self)
+{
+  self->edge_side = -1;
+}
+
+static void
+ide_editor_spell_language_popover_language_chooser_iface_init (GspellLanguageChooserInterface *iface)
+{
+  iface->get_language_full = ide_editor_spell_language_popover_get_language_full;
+  iface->set_language = ide_editor_spell_language_popover_set_language;
+}
diff --git a/libide/editor/ide-editor-spell-language-popover.h 
b/libide/editor/ide-editor-spell-language-popover.h
new file mode 100644
index 0000000..d50d166
--- /dev/null
+++ b/libide/editor/ide-editor-spell-language-popover.h
@@ -0,0 +1,36 @@
+/* ide-editor-spell-language-popover.h
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_EDITOR_SPELL_LANGUAGE_POPOVER_H
+#define IDE_EDITOR_SPELL_LANGUAGE_POPOVER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gspell/gspell.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_EDITOR_SPELL_LANGUAGE_POPOVER (ide_editor_spell_language_popover_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeEditorSpellLanguagePopover, ide_editor_spell_language_popover, IDE, 
EDITOR_SPELL_LANGUAGE_POPOVER, GtkButton)
+
+IdeEditorSpellLanguagePopover *ide_editor_spell_language_popover_new (const GspellLanguage 
*current_language);
+
+G_END_DECLS
+
+#endif /* IDE_EDITOR_SPELL_LANGUAGE_POPOVER_H */


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