[gnome-builder] prefs: add sub page support for language preferences



commit 455ce33c3b64dc0934cf4194419232f7e9f36197
Author: Christian Hergert <christian hergert me>
Date:   Tue Nov 10 17:12:45 2015 -0800

    prefs: add sub page support for language preferences

 data/ui/ide-preferences-language-row.ui            |   26 +++
 data/ui/ide-preferences-perspective.ui             |   11 ++
 libide/Makefile.am                                 |    4 +
 libide/preferences/ide-preferences-bin-private.h   |    6 +-
 libide/preferences/ide-preferences-builtin.c       |   37 ++---
 libide/preferences/ide-preferences-group-private.h |   31 ++++
 libide/preferences/ide-preferences-group.c         |   63 +++++++-
 libide/preferences/ide-preferences-language-row.c  |  167 ++++++++++++++++++++
 libide/preferences/ide-preferences-language-row.h  |   32 ++++
 libide/preferences/ide-preferences-page-private.h  |   31 ++++
 libide/preferences/ide-preferences-page.c          |   17 ++
 libide/preferences/ide-preferences-perspective.c   |   85 +++++++++-
 libide/preferences/ide-preferences.c               |   11 ++
 libide/preferences/ide-preferences.h               |    7 +
 libide/resources/libide.gresource.xml              |    1 +
 15 files changed, 491 insertions(+), 38 deletions(-)
---
diff --git a/data/ui/ide-preferences-language-row.ui b/data/ui/ide-preferences-language-row.ui
new file mode 100644
index 0000000..fe6bf1f
--- /dev/null
+++ b/data/ui/ide-preferences-language-row.ui
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.18 -->
+  <template class="IdePreferencesLanguageRow" parent="IdePreferencesBin">
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">horizontal</property>
+        <property name="spacing">12</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkLabel" id="title">
+            <property name="hexpand">true</property>
+            <property name="visible">true</property>
+            <property name="xalign">0.0</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage">
+            <property name="icon-name">pan-end-symbolic</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/data/ui/ide-preferences-perspective.ui b/data/ui/ide-preferences-perspective.ui
index 86bb475..2dd065c 100644
--- a/data/ui/ide-preferences-perspective.ui
+++ b/data/ui/ide-preferences-perspective.ui
@@ -39,5 +39,16 @@
   </template>
   <object class="IdeWorkbenchHeaderBar" id="titlebar">
     <property name="visible">true</property>
+    <child>
+                       <object class="GtkButton" id="back_button">
+                               <property name="action-name">perspective.go-back</property>
+                               <child>
+                                       <object class="GtkImage">
+                                               <property name="icon-name">go-previous-symbolic</property>
+                                               <property name="visible">true</property>
+                                       </object>
+                               </child>
+                       </object>
+    </child>
   </object>
 </interface>
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 56bd626..3987f96 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -281,8 +281,12 @@ libide_1_0_la_SOURCES = \
        preferences/ide-preferences-font-button.h \
        preferences/ide-preferences-group.c \
        preferences/ide-preferences-group.h \
+       preferences/ide-preferences-group-private.h \
+       preferences/ide-preferences-language-row.c \
+       preferences/ide-preferences-language-row.h \
        preferences/ide-preferences-page.c \
        preferences/ide-preferences-page.h \
+       preferences/ide-preferences-page-private.h \
        preferences/ide-preferences-perspective.c \
        preferences/ide-preferences-perspective.h \
        preferences/ide-preferences-spin-button.c \
diff --git a/libide/preferences/ide-preferences-bin-private.h 
b/libide/preferences/ide-preferences-bin-private.h
index a5a79d8..a005bfd 100644
--- a/libide/preferences/ide-preferences-bin-private.h
+++ b/libide/preferences/ide-preferences-bin-private.h
@@ -19,12 +19,12 @@
 #ifndef IDE_PREFERENCES_BIN_PRIVATE_H
 #define IDE_PREFERENCES_BIN_PRIVATE_H
 
-#include "ide-preferences-container.h"
+#include "ide-preferences-bin.h"
 
 G_BEGIN_DECLS
 
-void _ide_preferences_container_set_map (IdePreferencesBin *self,
-                                         GHashTable              *map);
+void _ide_preferences_bin_set_map (IdePreferencesBin *self,
+                                   GHashTable        *map);
 
 G_END_DECLS
 
diff --git a/libide/preferences/ide-preferences-builtin.c b/libide/preferences/ide-preferences-builtin.c
index 1b033a0..df9e1df 100644
--- a/libide/preferences/ide-preferences-builtin.c
+++ b/libide/preferences/ide-preferences-builtin.c
@@ -23,6 +23,7 @@
 
 #include "ide-preferences-builtin.h"
 #include "ide-preferences-entry.h"
+#include "ide-preferences-language-row.h"
 
 static void
 ide_preferences_builtin_register_plugins (IdePreferences *preferences)
@@ -288,48 +289,34 @@ ide_preferences_builtin_register_languages (IdePreferences *preferences)
 
   for (i = 0; language_ids [i]; i++)
     {
+      IdePreferencesLanguageRow *row;
       GtkSourceLanguage *language;
-      GtkBox *box;
-      GtkImage *arrow;
-      GtkLabel *title;
       const gchar *name;
 
       language = gtk_source_language_manager_get_language (manager, language_ids [i]);
       name = gtk_source_language_get_name (language);
 
-      box = g_object_new (GTK_TYPE_BOX,
+      row = g_object_new (IDE_TYPE_PREFERENCES_LANGUAGE_ROW,
+                          "id", language_ids [i],
+                          "title", name,
                           "visible", TRUE,
-                          "orientation", GTK_ORIENTATION_HORIZONTAL,
                           NULL);
-      title = g_object_new (GTK_TYPE_LABEL,
-                            "hexpand", TRUE,
-                            "label", name,
-                            "visible", TRUE,
-                            "xalign", 0.0f,
-                            NULL);
-      arrow = g_object_new (GTK_TYPE_IMAGE,
-                            "icon-name", "pan-end-symbolic",
-                            "visible", TRUE,
-                            NULL);
-      gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (title));
-      gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (arrow));
-
-      ide_preferences_add_custom (preferences, "languages", "list", GTK_WIDGET (box), NULL, 0);
+      ide_preferences_add_custom (preferences, "languages", "list", GTK_WIDGET (row), NULL, 0);
     }
 
   ide_preferences_add_page (preferences, "languages.id", NULL, 0);
 
   ide_preferences_add_list_group (preferences, "languages.id", "basic", NULL, 0);
-  ide_preferences_add_switch (preferences, "languages.id", "basic", "org.gnome.builder.editor.language", 
"trim-trailing-whitespace", "/org/gnome/builder/editor/language/{id}", NULL, _("Trim trialing whitespace"), 
_("Upon saving, trailing whitespcae from modified lines will be trimmed."), NULL, 10);
+  ide_preferences_add_switch (preferences, "languages.id", "basic", "org.gnome.builder.editor.language", 
"trim-trailing-whitespace", "/org/gnome/builder/editor/language/{id}/", NULL, _("Trim trialing whitespace"), 
_("Upon saving, trailing whitespcae from modified lines will be trimmed."), NULL, 10);
 
   ide_preferences_add_list_group (preferences, "languages.id", "margin", NULL, 0);
-  ide_preferences_add_radio (preferences, "languages.id", "margin", "org.gnome.builder.editor.language", 
"show-right-margin", "/org/gnome/builder/editor/language/{id}", NULL, _("Show right margin"), NULL, NULL, 0);
-  ide_preferences_add_spin_button (preferences, "languages.id", "margin", 
"org.gnome.builder.editor.language", "right-margin-position", "/org/gnome/builder/editor/language/{id}", 
_("Right margin position"), NULL, NULL, 10);
+  ide_preferences_add_radio (preferences, "languages.id", "margin", "org.gnome.builder.editor.language", 
"show-right-margin", "/org/gnome/builder/editor/language/{id}/", NULL, _("Show right margin"), NULL, NULL, 0);
+  ide_preferences_add_spin_button (preferences, "languages.id", "margin", 
"org.gnome.builder.editor.language", "right-margin-position", "/org/gnome/builder/editor/language/{id}/", 
_("Right margin position"), _("Position in spaces for the right margin"), NULL, 10);
 
   ide_preferences_add_list_group (preferences, "languages.id", "indentation", _("Indentation"), 100);
-  ide_preferences_add_spin_button (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "tab-width", "/org/gnome/builder/editor/language/{id}", _("Tab width"), 
NULL, NULL, 10);
-  ide_preferences_add_radio (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "insert-spaces-instead-of-tabs", 
"/org/gnome/builder/editor/language/{id}", NULL, _("Insert spaces instead of tabs"), NULL, NULL, 20);
-  ide_preferences_add_radio (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "auto-indent", "/org/gnome/builder/editor/language/{id}", NULL, _("Auto 
indent"), _("Indent source code as you type"), NULL, 30);
+  ide_preferences_add_spin_button (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "tab-width", "/org/gnome/builder/editor/language/{id}/", _("Tab width"), 
_("Width of a tab character in spaces"), NULL, 10);
+  ide_preferences_add_radio (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "insert-spaces-instead-of-tabs", 
"/org/gnome/builder/editor/language/{id}/", NULL, _("Insert spaces instead of tabs"), _("Prefer spaces over 
use of tabs"), NULL, 20);
+  ide_preferences_add_radio (preferences, "languages.id", "indentation", 
"org.gnome.builder.editor.language", "auto-indent", "/org/gnome/builder/editor/language/{id}/", NULL, 
_("Automatically indent"), _("Indent source code as you type"), NULL, 30);
 }
 
 void
diff --git a/libide/preferences/ide-preferences-group-private.h 
b/libide/preferences/ide-preferences-group-private.h
new file mode 100644
index 0000000..cf7c277
--- /dev/null
+++ b/libide/preferences/ide-preferences-group-private.h
@@ -0,0 +1,31 @@
+/* ide-preferences-group-private.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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_PREFERENCES_GROUP_PRIVATE_H
+#define IDE_PREFERENCES_GROUP_PRIVATE_H
+
+#include "ide-preferences-group.h"
+
+G_BEGIN_DECLS
+
+void _ide_preferences_group_set_map (IdePreferencesGroup *self,
+                                     GHashTable          *map);
+
+G_END_DECLS
+
+#endif /* IDE_PREFERENCES_GROUP_PRIVATE_H */
diff --git a/libide/preferences/ide-preferences-group.c b/libide/preferences/ide-preferences-group.c
index 0243676..c82d0d8 100644
--- a/libide/preferences/ide-preferences-group.c
+++ b/libide/preferences/ide-preferences-group.c
@@ -17,6 +17,7 @@
  */
 
 #include "ide-preferences-bin.h"
+#include "ide-preferences-bin-private.h"
 #include "ide-preferences-group.h"
 
 struct _IdePreferencesGroup
@@ -30,6 +31,8 @@ struct _IdePreferencesGroup
   GtkBox     *box;
   GtkListBox *list_box;
   GtkFrame   *list_box_frame;
+
+  GPtrArray  *widgets;
 };
 
 G_DEFINE_TYPE (IdePreferencesGroup, ide_preferences_group, GTK_TYPE_BIN)
@@ -45,6 +48,16 @@ enum {
 static GParamSpec *properties [LAST_PROP];
 
 static void
+ide_preferences_group_widget_destroy (IdePreferencesGroup *self,
+                                      GtkWidget           *widget)
+{
+  g_assert (IDE_IS_PREFERENCES_GROUP (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  g_ptr_array_remove (self->widgets, widget);
+}
+
+static void
 ide_preferences_group_row_activated (IdePreferencesGroup *self,
                                      GtkListBoxRow       *row,
                                      GtkListBox          *list_box)
@@ -61,6 +74,16 @@ ide_preferences_group_row_activated (IdePreferencesGroup *self,
 }
 
 static void
+ide_preferences_group_finalize (GObject *object)
+{
+  IdePreferencesGroup *self = (IdePreferencesGroup *)object;
+
+  g_clear_pointer (&self->widgets, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (ide_preferences_group_parent_class)->finalize (object);
+}
+
+static void
 ide_preferences_group_get_property (GObject    *object,
                                     guint       prop_id,
                                     GValue     *value,
@@ -123,6 +146,7 @@ ide_preferences_group_class_init (IdePreferencesGroupClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  object_class->finalize = ide_preferences_group_finalize;
   object_class->get_property = ide_preferences_group_get_property;
   object_class->set_property = ide_preferences_group_set_property;
 
@@ -161,6 +185,8 @@ ide_preferences_group_class_init (IdePreferencesGroupClass *klass)
 static void
 ide_preferences_group_init (IdePreferencesGroup *self)
 {
+  self->widgets = g_ptr_array_new ();
+
   gtk_widget_init_template (GTK_WIDGET (self));
 
   g_signal_connect_object (self->list_box,
@@ -179,14 +205,26 @@ ide_preferences_group_add (IdePreferencesGroup *self,
   g_return_if_fail (IDE_IS_PREFERENCES_GROUP (self));
   g_return_if_fail (IDE_IS_PREFERENCES_BIN (widget));
 
+  g_ptr_array_add (self->widgets, widget);
+
+  g_signal_connect_object (widget,
+                           "destroy",
+                           G_CALLBACK (ide_preferences_group_widget_destroy),
+                           self,
+                           G_CONNECT_SWAPPED);
+
   if (self->is_list)
     {
       GtkWidget *row;
 
-      row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
-                          "child", widget,
-                          "visible", TRUE,
-                          NULL);
+      if (GTK_IS_LIST_BOX_ROW (widget))
+        row = widget;
+      else
+        row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+                            "child", widget,
+                            "visible", TRUE,
+                            NULL);
+
       gtk_container_add (GTK_CONTAINER (self->list_box), row);
     }
   else
@@ -196,3 +234,20 @@ ide_preferences_group_add (IdePreferencesGroup *self,
                                          NULL);
     }
 }
+
+void
+_ide_preferences_group_set_map (IdePreferencesGroup *self,
+                                GHashTable          *map)
+{
+  guint i;
+
+  g_return_if_fail (IDE_IS_PREFERENCES_GROUP (self));
+
+  for (i = 0; i < self->widgets->len; i++)
+    {
+      GtkWidget *widget = g_ptr_array_index (self->widgets, i);
+
+      if (IDE_IS_PREFERENCES_BIN (widget))
+        _ide_preferences_bin_set_map (IDE_PREFERENCES_BIN (widget), map);
+    }
+}
diff --git a/libide/preferences/ide-preferences-language-row.c 
b/libide/preferences/ide-preferences-language-row.c
new file mode 100644
index 0000000..833957f
--- /dev/null
+++ b/libide/preferences/ide-preferences-language-row.c
@@ -0,0 +1,167 @@
+/* ide-preferences-language-row.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "ide-preferences.h"
+#include "ide-preferences-language-row.h"
+
+struct _IdePreferencesLanguageRow
+{
+  IdePreferencesBin parent_instance;
+  gchar *id;
+  GtkLabel *title;
+};
+
+G_DEFINE_TYPE (IdePreferencesLanguageRow, ide_preferences_language_row, IDE_TYPE_PREFERENCES_BIN)
+
+enum {
+  PROP_0,
+  PROP_ID,
+  PROP_TITLE,
+  LAST_PROP
+};
+
+enum {
+  ACTIVATE,
+  LAST_SIGNAL
+};
+
+static GParamSpec *properties [LAST_PROP];
+static guint signals [LAST_SIGNAL];
+
+static void
+ide_preferences_language_row_activate (IdePreferencesLanguageRow *self)
+{
+  GtkWidget *preferences;
+  GHashTable *map;
+
+  g_assert (IDE_IS_PREFERENCES_LANGUAGE_ROW (self));
+
+  if (self->id == NULL)
+    return;
+
+  preferences = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_PREFERENCES);
+  if (preferences == NULL)
+    return;
+
+  map = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+  g_hash_table_insert (map, "{id}", g_strdup (self->id));
+  ide_preferences_set_page (IDE_PREFERENCES (preferences), "languages.id", map);
+  g_hash_table_unref (map);
+}
+
+static void
+ide_preferences_language_row_get_property (GObject    *object,
+                                           guint       prop_id,
+                                           GValue     *value,
+                                           GParamSpec *pspec)
+{
+  IdePreferencesLanguageRow *self = IDE_PREFERENCES_LANGUAGE_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      g_value_set_string (value, self->id);
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, gtk_label_get_label (self->title));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_preferences_language_row_set_property (GObject      *object,
+                                           guint         prop_id,
+                                           const GValue *value,
+                                           GParamSpec   *pspec)
+{
+  IdePreferencesLanguageRow *self = IDE_PREFERENCES_LANGUAGE_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      self->id = g_value_dup_string (value);
+      break;
+
+    case PROP_TITLE:
+      gtk_label_set_label (self->title, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_preferences_language_row_finalize (GObject *object)
+{
+  IdePreferencesLanguageRow *self = (IdePreferencesLanguageRow *)object;
+
+  g_clear_pointer (&self->id, g_free);
+
+  G_OBJECT_CLASS (ide_preferences_language_row_parent_class)->finalize (object);
+}
+
+static void
+ide_preferences_language_row_class_init (IdePreferencesLanguageRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = ide_preferences_language_row_finalize;
+  object_class->get_property = ide_preferences_language_row_get_property;
+  object_class->set_property = ide_preferences_language_row_set_property;
+
+  properties [PROP_ID] =
+    g_param_spec_string ("id",
+                         "Id",
+                         "Id",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_TITLE] =
+    g_param_spec_string ("title",
+                         "Title",
+                         "Title",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+  signals [ACTIVATE] =
+    g_signal_new_class_handler ("activate",
+                                G_TYPE_FROM_CLASS (klass),
+                                G_SIGNAL_RUN_FIRST,
+                                G_CALLBACK (ide_preferences_language_row_activate),
+                                NULL, NULL, NULL,
+                                G_TYPE_NONE, 0);
+
+  widget_class->activate_signal = signals [ACTIVATE];
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-preferences-language-row.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdePreferencesLanguageRow, title);
+}
+
+static void
+ide_preferences_language_row_init (IdePreferencesLanguageRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/libide/preferences/ide-preferences-language-row.h 
b/libide/preferences/ide-preferences-language-row.h
new file mode 100644
index 0000000..963fd79
--- /dev/null
+++ b/libide/preferences/ide-preferences-language-row.h
@@ -0,0 +1,32 @@
+/* ide-preferences-language-row.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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_PREFERENCES_LANGUAGE_ROW_H
+#define IDE_PREFERENCES_LANGUAGE_ROW_H
+
+#include "ide-preferences-bin.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PREFERENCES_LANGUAGE_ROW (ide_preferences_language_row_get_type())
+
+G_DECLARE_FINAL_TYPE (IdePreferencesLanguageRow, ide_preferences_language_row, IDE, 
PREFERENCES_LANGUAGE_ROW, IdePreferencesBin)
+
+G_END_DECLS
+
+#endif /* IDE_PREFERENCES_LANGUAGE_ROW_H */
diff --git a/libide/preferences/ide-preferences-page-private.h 
b/libide/preferences/ide-preferences-page-private.h
new file mode 100644
index 0000000..df52ae3
--- /dev/null
+++ b/libide/preferences/ide-preferences-page-private.h
@@ -0,0 +1,31 @@
+/* ide-preferences-page-private.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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_PREFERENCES_PAGE_PRIVATE_H
+#define IDE_PREFERENCES_PAGE_PRIVATE_H
+
+#include "ide-preferences-page.h"
+
+G_BEGIN_DECLS
+
+void _ide_preferences_page_set_map (IdePreferencesPage *self,
+                                    GHashTable         *map);
+
+G_END_DECLS
+
+#endif /* IDE_PREFERENCES_PAGE_PRIVATE_H */
diff --git a/libide/preferences/ide-preferences-page.c b/libide/preferences/ide-preferences-page.c
index a13daa1..c241759 100644
--- a/libide/preferences/ide-preferences-page.c
+++ b/libide/preferences/ide-preferences-page.c
@@ -19,7 +19,9 @@
 #include <glib/gi18n.h>
 
 #include "ide-preferences-group.h"
+#include "ide-preferences-group-private.h"
 #include "ide-preferences-page.h"
+#include "ide-preferences-page-private.h"
 
 struct _IdePreferencesPage
 {
@@ -156,3 +158,18 @@ ide_preferences_page_get_group (IdePreferencesPage *self,
 
   return g_hash_table_lookup (self->groups_by_name, name);
 }
+
+void
+_ide_preferences_page_set_map (IdePreferencesPage *self,
+                               GHashTable         *map)
+{
+  IdePreferencesGroup *group;
+  GHashTableIter iter;
+
+  g_return_if_fail (IDE_IS_PREFERENCES_PAGE (self));
+
+  g_hash_table_iter_init (&iter, self->groups_by_name);
+
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&group))
+    _ide_preferences_group_set_map (group, map);
+}
diff --git a/libide/preferences/ide-preferences-perspective.c 
b/libide/preferences/ide-preferences-perspective.c
index 52424e8..f71de85 100644
--- a/libide/preferences/ide-preferences-perspective.c
+++ b/libide/preferences/ide-preferences-perspective.c
@@ -28,6 +28,7 @@
 #include "ide-preferences-font-button.h"
 #include "ide-preferences-group.h"
 #include "ide-preferences-page.h"
+#include "ide-preferences-page-private.h"
 #include "ide-preferences-perspective.h"
 #include "ide-preferences-spin-button.h"
 #include "ide-preferences-switch.h"
@@ -39,10 +40,12 @@ struct _IdePreferencesPerspective
 
   guint                  last_widget_id;
 
+  GActionGroup          *actions;
   PeasExtensionSet      *extensions;
   GSequence             *pages;
   GHashTable            *widgets;
 
+  GtkButton             *back_button;
   GtkStack              *page_stack;
   GtkStackSwitcher      *page_stack_sidebar;
   GtkStack              *subpage_stack;
@@ -128,6 +131,7 @@ ide_preferences_perspective_finalize (GObject *object)
 
   g_clear_pointer (&self->pages, g_sequence_free);
   g_clear_pointer (&self->widgets, g_hash_table_unref);
+  g_clear_object (&self->actions);
 
   G_OBJECT_CLASS (ide_preferences_perspective_parent_class)->finalize (object);
 }
@@ -142,6 +146,7 @@ ide_preferences_perspective_class_init (IdePreferencesPerspectiveClass *klass)
   object_class->finalize = ide_preferences_perspective_finalize;
 
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-preferences-perspective.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdePreferencesPerspective, back_button);
   gtk_widget_class_bind_template_child (widget_class, IdePreferencesPerspective, page_stack_sidebar);
   gtk_widget_class_bind_template_child (widget_class, IdePreferencesPerspective, page_stack);
   gtk_widget_class_bind_template_child (widget_class, IdePreferencesPerspective, subpage_stack);
@@ -150,13 +155,34 @@ ide_preferences_perspective_class_init (IdePreferencesPerspectiveClass *klass)
 }
 
 static void
+go_back_activate (GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       user_data)
+{
+  IdePreferencesPerspective *self = user_data;
+
+  g_assert (IDE_IS_PREFERENCES_PERSPECTIVE (self));
+
+  gtk_stack_set_visible_child (self->top_stack, GTK_WIDGET (self->page_stack));
+  gtk_widget_hide (GTK_WIDGET (self->back_button));
+}
+
+static void
 ide_preferences_perspective_init (IdePreferencesPerspective *self)
 {
+  static const GActionEntry entries[] = {
+    { "go-back", go_back_activate },
+  };
+
   gtk_widget_init_template (GTK_WIDGET (self));
 
   self->pages = g_sequence_new (NULL);
   self->widgets = g_hash_table_new (g_direct_hash, g_direct_equal);
 
+  self->actions = G_ACTION_GROUP (g_simple_action_group_new ());
+  g_action_map_add_action_entries (G_ACTION_MAP (self->actions),
+                                   entries, G_N_ELEMENTS (entries), self);
+
   gtk_stack_set_visible_child (self->top_stack, GTK_WIDGET (self->page_stack));
 }
 
@@ -589,12 +615,15 @@ ide_preferences_perspective_add_custom (IdePreferences *preferences,
       return 0;
     }
 
-  container = g_object_new (IDE_TYPE_PREFERENCES_BIN,
-                            "child", widget,
-                            "keywords", keywords,
-                            "priority", priority,
-                            "visible", TRUE,
-                            NULL);
+  if (IDE_IS_PREFERENCES_BIN (widget))
+    container = IDE_PREFERENCES_BIN (widget);
+  else
+    container = g_object_new (IDE_TYPE_PREFERENCES_BIN,
+                              "child", widget,
+                              "keywords", keywords,
+                              "priority", priority,
+                              "visible", TRUE,
+                              NULL);
 
   ide_preferences_group_add (group, GTK_WIDGET (container));
 
@@ -605,6 +634,38 @@ ide_preferences_perspective_add_custom (IdePreferences *preferences,
 }
 
 static void
+ide_preferences_perspective_set_page (IdePreferences *preferences,
+                                      const gchar    *page_name,
+                                      GHashTable     *map)
+{
+  IdePreferencesPerspective *self = (IdePreferencesPerspective *)preferences;
+  GtkWidget *page;
+
+  g_assert (IDE_IS_PREFERENCES_PERSPECTIVE (self));
+  g_assert (page_name != NULL);
+
+  page = ide_preferences_perspective_get_page (self, page_name);
+
+  if (page == NULL)
+    {
+      g_warning ("No such page \"%s\"", page_name);
+      return;
+    }
+
+  if (strchr (page_name, '.') != NULL)
+    {
+      _ide_preferences_page_set_map (IDE_PREFERENCES_PAGE (page), map);
+      gtk_stack_set_visible_child (self->subpage_stack, page);
+      gtk_stack_set_visible_child (self->top_stack, GTK_WIDGET (self->subpage_stack));
+      gtk_widget_set_visible (GTK_WIDGET (self->back_button), TRUE);
+      return;
+    }
+
+  gtk_stack_set_visible_child (self->page_stack, page);
+  gtk_widget_set_visible (GTK_WIDGET (self->back_button), FALSE);
+}
+
+static void
 ide_preferences_iface_init (IdePreferencesInterface *iface)
 {
   iface->add_page = ide_preferences_perspective_add_page;
@@ -615,6 +676,7 @@ ide_preferences_iface_init (IdePreferencesInterface *iface)
   iface->add_switch = ide_preferences_perspective_add_switch;
   iface->add_spin_button = ide_preferences_perspective_add_spin_button;
   iface->add_custom = ide_preferences_perspective_add_custom;
+  iface->set_page = ide_preferences_perspective_set_page;
 }
 
 static gchar *
@@ -635,10 +697,21 @@ ide_preferences_perspective_get_titlebar (IdePerspective *perspective)
   return GTK_WIDGET (IDE_PREFERENCES_PERSPECTIVE (perspective)->titlebar);
 }
 
+static GActionGroup *
+ide_preferences_perspective_get_actions (IdePerspective *perspective)
+{
+  IdePreferencesPerspective *self = (IdePreferencesPerspective *)perspective;
+
+  g_assert (IDE_IS_PREFERENCES_PERSPECTIVE (self));
+
+  return g_object_ref (self->actions);
+}
+
 static void
 ide_perspective_iface_init (IdePerspectiveInterface *iface)
 {
   iface->get_icon_name = ide_preferences_perspective_get_icon_name;
   iface->get_title = ide_preferences_perspective_get_title;
   iface->get_titlebar = ide_preferences_perspective_get_titlebar;
+  iface->get_actions = ide_preferences_perspective_get_actions;
 }
diff --git a/libide/preferences/ide-preferences.c b/libide/preferences/ide-preferences.c
index 674bec7..97ff8f0 100644
--- a/libide/preferences/ide-preferences.c
+++ b/libide/preferences/ide-preferences.c
@@ -179,3 +179,14 @@ ide_preferences_add_font_button (IdePreferences *self,
 
   return IDE_PREFERENCES_GET_IFACE (self)->add_font_button (self, page_name, group_name, schema_id, key, 
title, keywords, priority);
 }
+
+void
+ide_preferences_set_page (IdePreferences *self,
+                          const gchar    *page_name,
+                          GHashTable     *map)
+{
+  g_return_if_fail (IDE_IS_PREFERENCES (self));
+  g_return_if_fail (page_name != NULL);
+
+  IDE_PREFERENCES_GET_IFACE (self)->set_page (self, page_name, map);
+}
diff --git a/libide/preferences/ide-preferences.h b/libide/preferences/ide-preferences.h
index 4c74f72..b63148a 100644
--- a/libide/preferences/ide-preferences.h
+++ b/libide/preferences/ide-preferences.h
@@ -31,6 +31,9 @@ struct _IdePreferencesInterface
 {
   GTypeInterface parent_interface;
 
+  void  (*set_page)        (IdePreferences *self,
+                            const gchar    *page_name,
+                            GHashTable     *map);
   void  (*add_page)        (IdePreferences *self,
                             const gchar    *page_name,
                             const gchar    *title,
@@ -153,6 +156,10 @@ guint ide_preferences_add_font_button (IdePreferences *self,
                                        const gchar    *title,
                                        const gchar    *keywords,
                                        gint            priority);
+void  ide_preferences_set_page        (IdePreferences *self,
+                                       const gchar    *page_name,
+                                       GHashTable     *map);
+
 
 G_END_DECLS
 
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index 3908a93..35d6560 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -28,6 +28,7 @@
     <file alias="ui/ide-preferences-entry.ui">../../data/ui/ide-preferences-entry.ui</file>
     <file alias="ui/ide-preferences-font-button.ui">../../data/ui/ide-preferences-font-button.ui</file>
     <file alias="ui/ide-preferences-group.ui">../../data/ui/ide-preferences-group.ui</file>
+    <file alias="ui/ide-preferences-language-row.ui">../../data/ui/ide-preferences-language-row.ui</file>
     <file alias="ui/ide-preferences-page.ui">../../data/ui/ide-preferences-page.ui</file>
     <file alias="ui/ide-preferences-perspective.ui">../../data/ui/ide-preferences-perspective.ui</file>
     <file alias="ui/ide-preferences-spin-button.ui">../../data/ui/ide-preferences-spin-button.ui</file>


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