[gnome-builder] editor: implement language filtering in properties
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] editor: implement language filtering in properties
- Date: Wed, 19 Jul 2017 11:13:45 +0000 (UTC)
commit a571978744a1ddae1ddc01e6c5f1a3a128e664ef
Author: Christian Hergert <chergert redhat com>
Date: Fri Jul 7 21:31:46 2017 -0700
editor: implement language filtering in properties
libide/editor/ide-editor-properties.c | 302 ++++++++++++++++++++++++++++++--
libide/editor/ide-editor-properties.ui | 44 +++++-
2 files changed, 334 insertions(+), 12 deletions(-)
---
diff --git a/libide/editor/ide-editor-properties.c b/libide/editor/ide-editor-properties.c
index 458c7e7..fe211c6 100644
--- a/libide/editor/ide-editor-properties.c
+++ b/libide/editor/ide-editor-properties.c
@@ -20,6 +20,9 @@
#include <dazzle.h>
+#include "ide-macros.h"
+
+#include "buffers/ide-buffer.h"
#include "editor/ide-editor-properties.h"
/**
@@ -36,15 +39,26 @@
struct _IdeEditorProperties
{
- GtkBin parent_instance;
+ GtkBin parent_instance;
+
+ DzlSignalGroup *buffer_signals;
- GtkCheckButton *show_line_numbers;
- GtkCheckButton *show_right_margin;
- GtkCheckButton *highlight_current_line;
- GtkCheckButton *insert_trailing_newline;
- GtkCheckButton *overwrite_braces;
- GtkCheckButton *auto_indent;
- GtkCheckButton *smart_backspace;
+ /* Unowned references */
+ IdeEditorView *view;
+
+ /* Template references */
+ GtkCheckButton *show_line_numbers;
+ GtkCheckButton *show_right_margin;
+ GtkCheckButton *highlight_current_line;
+ GtkCheckButton *insert_trailing_newline;
+ GtkCheckButton *overwrite_braces;
+ GtkCheckButton *auto_indent;
+ GtkCheckButton *smart_backspace;
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *language_column;
+ GtkCellRendererText *language_cell;
+ GtkListStore *languages;
+ GtkSearchEntry *entry;
};
enum {
@@ -58,6 +72,227 @@ G_DEFINE_TYPE (IdeEditorProperties, ide_editor_properties, GTK_TYPE_BIN)
static GParamSpec *properties [N_PROPS];
static void
+ide_editor_properties_cell_data_func (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ g_autoptr(GtkSourceLanguage) language = NULL;
+ const gchar *text = NULL;
+
+ gtk_tree_model_get (tree_model, iter, 0, &language, -1);
+
+ if (language != NULL)
+ text = gtk_source_language_get_name (language);
+
+ g_object_set (cell, "text", text, NULL);
+}
+
+static void
+ide_editor_properties_language_activated (IdeEditorProperties *self,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GtkTreeView *tree_view)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_assert (IDE_IS_EDITOR_PROPERTIES (self));
+ g_assert (path != NULL);
+ g_assert (column != NULL);
+ g_assert (GTK_IS_TREE_VIEW (tree_view));
+
+ model = gtk_tree_view_get_model (tree_view);
+
+ if (gtk_tree_model_get_iter (model, &iter, path))
+ {
+ g_autoptr(GtkSourceLanguage) language = NULL;
+
+ gtk_tree_model_get (model, &iter, 0, &language, -1);
+ if (language != NULL && self->view != NULL)
+ ide_editor_view_set_language (self->view, language);
+ }
+}
+
+static gint
+compare_languages (gconstpointer a,
+ gconstpointer b,
+ gpointer data)
+{
+ GtkSourceLanguage *al = (GtkSourceLanguage *)a;
+ GtkSourceLanguage *bl = (GtkSourceLanguage *)b;
+
+ return g_utf8_collate (gtk_source_language_get_name (al),
+ gtk_source_language_get_name (bl));
+}
+
+static gboolean
+language_equal (GtkSourceLanguage *a,
+ GtkSourceLanguage *b)
+{
+ return a == b ||
+ g_strcmp0 (gtk_source_language_get_name (a),
+ gtk_source_language_get_name (b)) == 0;
+}
+
+static void
+ide_editor_properties_notify_language (IdeEditorProperties *self,
+ GParamSpec *pspec,
+ IdeBuffer *buffer)
+{
+ GtkSourceLanguage *language;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_assert (IDE_IS_EDITOR_PROPERTIES (self));
+ g_assert (IDE_IS_BUFFER (buffer));
+
+ selection = gtk_tree_view_get_selection (self->tree_view);
+ language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer));
+
+ if (language == NULL)
+ {
+ gtk_tree_selection_unselect_all (selection);
+ return;
+ }
+
+ /* Model might be a filter */
+ model = gtk_tree_view_get_model (self->tree_view);
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ do
+ {
+ g_autoptr(GtkSourceLanguage) ele = NULL;
+
+ gtk_tree_model_get (model, &iter, 0, &ele, -1);
+
+ if (language_equal (language, ele))
+ {
+ GtkTreePath *path = NULL;
+
+ /* Be safe against re-entrancy */
+ if (!gtk_tree_selection_iter_is_selected (selection, &iter))
+ {
+ path = gtk_tree_model_get_path (model, &iter);
+ gtk_tree_selection_select_iter (selection, &iter);
+ gtk_tree_view_scroll_to_cell (self->tree_view, path, NULL, FALSE, 0, 0);
+ gtk_tree_path_free (path);
+ }
+
+ break;
+ }
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+static void
+ide_editor_properties_bind_buffer (IdeEditorProperties *self,
+ IdeBuffer *buffer,
+ DzlSignalGroup *signals)
+{
+ g_assert (IDE_IS_EDITOR_PROPERTIES (self));
+ g_assert (IDE_IS_BUFFER (buffer));
+ g_assert (DZL_IS_SIGNAL_GROUP (signals));
+
+ ide_editor_properties_notify_language (self, NULL, buffer);
+}
+
+static void
+ide_editor_properties_reload_languages (IdeEditorProperties *self)
+{
+ GtkSourceLanguageManager *manager;
+ const gchar * const *ids;
+
+ g_assert (IDE_IS_EDITOR_PROPERTIES (self));
+
+ gtk_list_store_clear (self->languages);
+
+ manager = gtk_source_language_manager_get_default ();
+ ids = gtk_source_language_manager_get_language_ids (manager);
+
+ for (guint i = 0; ids[i] != NULL; i++)
+ {
+ GtkSourceLanguage *language = gtk_source_language_manager_get_language (manager, ids[i]);
+ const gchar *id = gtk_source_language_get_id (language);
+ GtkTreeIter iter;
+
+ /* ignore the "default values" language */
+ if (g_strcmp0 (id, "def") == 0)
+ continue;
+
+ dzl_gtk_list_store_insert_sorted (self->languages, &iter, language, 0,
+ compare_languages, NULL);
+ gtk_list_store_set (self->languages, &iter, 0, language, -1);
+ }
+}
+
+static gboolean
+ide_editor_properties_visibility_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ g_autoptr(GtkSourceLanguage) language = NULL;
+ DzlPatternSpec *spec = user_data;
+ const gchar *id;
+ const gchar *name;
+
+ g_assert (GTK_IS_TREE_MODEL (model));
+ g_assert (iter != NULL);
+ g_assert (spec != NULL);
+
+ gtk_tree_model_get (model, iter, 0, &language, -1);
+ g_assert (language != NULL);
+
+ id = gtk_source_language_get_id (language);
+ name = gtk_source_language_get_name (language);
+
+ return dzl_pattern_spec_match (spec, id) ||
+ dzl_pattern_spec_match (spec, name);
+}
+
+static void
+ide_editor_properties_entry_changed (IdeEditorProperties *self,
+ GtkSearchEntry *entry)
+{
+ g_autoptr(GtkTreeModel) filter = NULL;
+ const gchar *text;
+
+ g_assert (IDE_IS_EDITOR_PROPERTIES (self));
+ g_assert (GTK_IS_SEARCH_ENTRY (entry));
+
+ text = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ /* Clear any previous filter */
+ if (ide_str_empty0 (text))
+ {
+ gtk_tree_view_set_model (self->tree_view, GTK_TREE_MODEL (self->languages));
+ return;
+ }
+
+ /* We can't reuse existing filters, so create a new one */
+ filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (self->languages), NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+ ide_editor_properties_visibility_func,
+ dzl_pattern_spec_new (text),
+ (GDestroyNotify) dzl_pattern_spec_unref);
+ gtk_tree_view_set_model (self->tree_view, filter);
+}
+
+static void
+ide_editor_properties_constructed (GObject *object)
+{
+ IdeEditorProperties *self = (IdeEditorProperties *)object;
+
+ G_OBJECT_CLASS (ide_editor_properties_parent_class)->constructed (object);
+
+ ide_editor_properties_reload_languages (self);
+}
+
+static void
ide_editor_properties_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -82,6 +317,7 @@ ide_editor_properties_class_init (IdeEditorPropertiesClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ object_class->constructed = ide_editor_properties_constructed;
object_class->set_property = ide_editor_properties_set_property;
properties [PROP_VIEW] =
@@ -96,13 +332,18 @@ ide_editor_properties_class_init (IdeEditorPropertiesClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/ui/ide-editor-properties.ui");
- gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, show_line_numbers);
- gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, show_right_margin);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, auto_indent);
gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, highlight_current_line);
gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, insert_trailing_newline);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, language_cell);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, language_column);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, languages);
gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, overwrite_braces);
- gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, auto_indent);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, show_line_numbers);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, show_right_margin);
gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, smart_backspace);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, tree_view);
+ gtk_widget_class_bind_template_child (widget_class, IdeEditorProperties, entry);
gtk_widget_class_set_css_name (widget_class, "ideeditorproperties");
}
@@ -114,6 +355,18 @@ ide_editor_properties_init (IdeEditorProperties *self)
gtk_widget_init_template (GTK_WIDGET (self));
+ self->buffer_signals = dzl_signal_group_new (IDE_TYPE_BUFFER);
+
+ g_signal_connect_swapped (self->buffer_signals,
+ "bind",
+ G_CALLBACK (ide_editor_properties_bind_buffer),
+ self);
+
+ dzl_signal_group_connect_swapped (self->buffer_signals,
+ "notify::language",
+ G_CALLBACK (ide_editor_properties_notify_language),
+ self);
+
/* Swap direction so check is at opposite end of checkbutton */
dir = gtk_widget_get_direction (GTK_WIDGET (self));
dir = (dir != GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
@@ -124,6 +377,21 @@ ide_editor_properties_init (IdeEditorProperties *self)
gtk_widget_set_direction (GTK_WIDGET (self->overwrite_braces), dir);
gtk_widget_set_direction (GTK_WIDGET (self->auto_indent), dir);
gtk_widget_set_direction (GTK_WIDGET (self->smart_backspace), dir);
+
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self->language_column),
+ GTK_CELL_RENDERER (self->language_cell),
+ ide_editor_properties_cell_data_func,
+ self, NULL);
+
+ g_signal_connect_swapped (self->tree_view,
+ "row-activated",
+ G_CALLBACK (ide_editor_properties_language_activated),
+ self);
+
+ g_signal_connect_swapped (self->entry,
+ "changed",
+ G_CALLBACK (ide_editor_properties_entry_changed),
+ self);
}
/**
@@ -154,9 +422,21 @@ void
ide_editor_properties_set_view (IdeEditorProperties *self,
IdeEditorView *view)
{
+ IdeBuffer *buffer = NULL;
+
g_return_if_fail (IDE_IS_EDITOR_PROPERTIES (self));
g_return_if_fail (!view || IDE_IS_EDITOR_VIEW (view));
+ gtk_widget_set_sensitive (GTK_WIDGET (self), view != NULL);
+
+ /* No reference, we clear it when focus changes */
+ self->view = view;
+
+ /* Track the buffer for language changes */
+ if (view != NULL)
+ buffer = ide_editor_view_get_buffer (view);
+ dzl_signal_group_set_target (self->buffer_signals, buffer);
+
dzl_gtk_widget_mux_action_groups (GTK_WIDGET (self),
view ? GTK_WIDGET (view) : NULL,
"IDE_EDITOR_PROPERTY_ACTIONS");
diff --git a/libide/editor/ide-editor-properties.ui b/libide/editor/ide-editor-properties.ui
index 1ec731f..863ab57 100644
--- a/libide/editor/ide-editor-properties.ui
+++ b/libide/editor/ide-editor-properties.ui
@@ -232,6 +232,24 @@
<property name="visible">true</property>
<property name="orientation">vertical</property>
<child>
+ <object class="GtkLabel">
+ <property name="visible">true</property>
+ <property name="label" translatable="yes">Language Syntax</property>
+ <property name="margin-top">12</property>
+ <property name="margin-right">12</property>
+ <property name="margin-left">12</property>
+ <property name="margin-bottom">6</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <attributes>
+ <attribute name="scale" value="0.8333"/>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<property name="expand">true</property>
@@ -239,7 +257,26 @@
<property name="propagate-natural-height">true</property>
<child>
<object class="GtkTreeView" id="tree_view">
+ <property name="activate-on-single-click">true</property>
+ <property name="headers-visible">false</property>
+ <property name="model">languages</property>
<property name="visible">true</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection">
+ <property name="mode">browse</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="language_column">
+ <child>
+ <object class="GtkCellRendererText" id="language_cell">
+ <property name="xalign">0.0</property>
+ <property name="ypad">3</property>
+ <property name="xpad">12</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
</object>
@@ -254,7 +291,7 @@
<object class="GtkSearchEntry" id="entry">
<property name="has-frame">false</property>
<property name="visible">true</property>
- <property name="placeholder-text" translatable="yes">Search highlight modeā¦</property>
+ <property name="placeholder-text" translatable="yes">Search languagesā¦</property>
</object>
</child>
</object>
@@ -262,4 +299,9 @@
</object>
</child>
</template>
+ <object class="GtkListStore" id="languages">
+ <columns>
+ <column type="GtkSourceLanguage"/>
+ </columns>
+ </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]