[tepl] HighlightModeSelector: start to implement class



commit 22b222c1694f0768b538141eba4d98046e52422e
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Oct 30 00:22:49 2020 +0100

    HighlightModeSelector: start to implement class
    
    Inspired by GeditHighlightModeSelector, but uses a GtkListBox instead of
    GtkTreeView.

 docs/reference/tepl-docs.xml        |   1 +
 docs/reference/tepl-sections.txt    |  16 +++
 po/POTFILES.in                      |   1 +
 tepl/meson.build                    |   2 +
 tepl/tepl-highlight-mode-selector.c | 247 ++++++++++++++++++++++++++++++++++++
 tepl/tepl-highlight-mode-selector.h |  55 ++++++++
 tepl/tepl.h                         |   1 +
 7 files changed, 323 insertions(+)
---
diff --git a/docs/reference/tepl-docs.xml b/docs/reference/tepl-docs.xml
index a7dca6a..090c230 100644
--- a/docs/reference/tepl-docs.xml
+++ b/docs/reference/tepl-docs.xml
@@ -64,6 +64,7 @@
     <chapter id="misc">
       <title>Misc</title>
       <xi:include href="xml/goto-line-bar.xml"/>
+      <xi:include href="xml/highlight-mode-selector.xml"/>
       <xi:include href="xml/info-bar.xml"/>
       <xi:include href="xml/iter.xml"/>
       <xi:include href="xml/panel.xml"/>
diff --git a/docs/reference/tepl-sections.txt b/docs/reference/tepl-sections.txt
index 7a1f04d..cf1abd8 100644
--- a/docs/reference/tepl-sections.txt
+++ b/docs/reference/tepl-sections.txt
@@ -232,6 +232,22 @@ TEPL_TYPE_GUTTER_RENDERER_FOLDS_STATE
 tepl_gutter_renderer_folds_state_get_type
 </SECTION>
 
+<SECTION>
+<FILE>highlight-mode-selector</FILE>
+TeplHighlightModeSelector
+tepl_highlight_mode_selector_new
+<SUBSECTION Standard>
+TEPL_HIGHLIGHT_MODE_SELECTOR
+TEPL_HIGHLIGHT_MODE_SELECTOR_CLASS
+TEPL_HIGHLIGHT_MODE_SELECTOR_GET_CLASS
+TEPL_IS_HIGHLIGHT_MODE_SELECTOR
+TEPL_IS_HIGHLIGHT_MODE_SELECTOR_CLASS
+TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR
+TeplHighlightModeSelectorClass
+TeplHighlightModeSelectorPrivate
+tepl_highlight_mode_selector_get_type
+</SECTION>
+
 <SECTION>
 <FILE>info-bar</FILE>
 TeplInfoBar
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c89b4e0..0238724 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,6 +9,7 @@ tepl/tepl-file-chooser.c
 tepl/tepl-file-loader.c
 tepl/tepl-file-saver.c
 tepl/tepl-goto-line-bar.c
+tepl/tepl-highlight-mode-selector.c
 tepl/tepl-icu.c
 tepl/tepl-info-bar.c
 tepl/tepl-init.c
diff --git a/tepl/meson.build b/tepl/meson.build
index 3bd5248..0442571 100644
--- a/tepl/meson.build
+++ b/tepl/meson.build
@@ -11,6 +11,7 @@ tepl_public_headers = [
   'tepl-fold-region.h',
   'tepl-goto-line-bar.h',
   'tepl-gutter-renderer-folds.h',
+  'tepl-highlight-mode-selector.h',
   'tepl-info-bar.h',
   'tepl-init.h',
   'tepl-io-error-info-bars.h',
@@ -46,6 +47,7 @@ tepl_public_c_files = [
   'tepl-fold-region.c',
   'tepl-goto-line-bar.c',
   'tepl-gutter-renderer-folds.c',
+  'tepl-highlight-mode-selector.c',
   'tepl-info-bar.c',
   'tepl-init.c',
   'tepl-io-error-info-bars.c',
diff --git a/tepl/tepl-highlight-mode-selector.c b/tepl/tepl-highlight-mode-selector.c
new file mode 100644
index 0000000..545621a
--- /dev/null
+++ b/tepl/tepl-highlight-mode-selector.c
@@ -0,0 +1,247 @@
+/* SPDX-FileCopyrightText: 2020 - Sébastien Wilmet <swilmet gnome org>
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+
+#include "tepl-highlight-mode-selector.h"
+
+/**
+ * SECTION:highlight-mode-selector
+ * @Title: TeplHighlightModeSelector
+ * @Short_description: A widget for selecting a #GtkSourceLanguage
+ */
+
+struct _TeplHighlightModeSelectorPrivate
+{
+       GtkSearchEntry *search_entry;
+       GtkListBox *list_box;
+};
+
+enum
+{
+       SIGNAL_LANGUAGE_SELECTED,
+       N_SIGNALS
+};
+
+static guint signals[N_SIGNALS];
+
+#define LIST_BOX_ROW_LANGUAGE_KEY "language-key"
+
+G_DEFINE_TYPE_WITH_PRIVATE (TeplHighlightModeSelector, tepl_highlight_mode_selector, GTK_TYPE_GRID)
+
+static void
+list_box_row_set_language (GtkListBoxRow     *list_box_row,
+                          GtkSourceLanguage *language)
+{
+       g_object_set_data_full (G_OBJECT (list_box_row),
+                               LIST_BOX_ROW_LANGUAGE_KEY,
+                               g_object_ref (language),
+                               g_object_unref);
+}
+
+/* Returns: (transfer none). */
+static GtkSourceLanguage *
+list_box_row_get_language (GtkListBoxRow *list_box_row)
+{
+       return g_object_get_data (G_OBJECT (list_box_row), LIST_BOX_ROW_LANGUAGE_KEY);
+}
+
+static void
+tepl_highlight_mode_selector_dispose (GObject *object)
+{
+       TeplHighlightModeSelector *selector = TEPL_HIGHLIGHT_MODE_SELECTOR (object);
+
+       selector->priv->search_entry = NULL;
+       selector->priv->list_box = NULL;
+
+       G_OBJECT_CLASS (tepl_highlight_mode_selector_parent_class)->dispose (object);
+}
+
+static void
+tepl_highlight_mode_selector_class_init (TeplHighlightModeSelectorClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->dispose = tepl_highlight_mode_selector_dispose;
+
+       /**
+        * TeplHighlightModeSelector::language-selected:
+        * @selector: the #TeplHighlightModeSelector emitting the signal.
+        * @language: the #GtkSourceLanguage object that has been selected,
+        *   guaranteed to be non-%NULL.
+        *
+        * Since: 5.2
+        */
+       signals[SIGNAL_LANGUAGE_SELECTED] =
+               g_signal_new ("language-selected",
+                             G_TYPE_FROM_CLASS (klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (TeplHighlightModeSelectorClass, language_selected),
+                             NULL, NULL, NULL,
+                             G_TYPE_NONE, 1, GTK_SOURCE_TYPE_LANGUAGE);
+}
+
+static void
+populate_list_box (TeplHighlightModeSelector *selector)
+{
+       GtkSourceLanguageManager *language_manager;
+       const gchar * const *language_ids;
+       gint i;
+
+       language_manager = gtk_source_language_manager_get_default ();
+       language_ids = gtk_source_language_manager_get_language_ids (language_manager);
+
+       if (language_ids == NULL)
+       {
+               return;
+       }
+
+       for (i = 0; language_ids[i] != NULL; i++)
+       {
+               const gchar *cur_language_id = language_ids[i];
+               GtkSourceLanguage *language;
+               GtkLabel *label;
+               GtkListBoxRow *list_box_row;
+
+               language = gtk_source_language_manager_get_language (language_manager, cur_language_id);
+               if (gtk_source_language_get_hidden (language))
+               {
+                       continue;
+               }
+
+               label = GTK_LABEL (gtk_label_new (gtk_source_language_get_name (language)));
+               gtk_label_set_xalign (label, 0.0);
+
+               list_box_row = GTK_LIST_BOX_ROW (gtk_list_box_row_new ());
+               list_box_row_set_language (list_box_row, language);
+               gtk_container_add (GTK_CONTAINER (list_box_row), GTK_WIDGET (label));
+               gtk_container_add (GTK_CONTAINER (selector->priv->list_box), GTK_WIDGET (list_box_row));
+       }
+}
+
+static gboolean
+filter_cb (GtkListBoxRow *list_box_row,
+          gpointer       user_data)
+{
+       TeplHighlightModeSelector *selector = user_data;
+       const gchar *search_text;
+       GtkSourceLanguage *language;
+       const gchar *language_name;
+       gchar *language_name_normalized;
+       gchar *language_name_casefolded;
+       gchar *search_text_normalized;
+       gchar *search_text_casefolded;
+       gboolean visible;
+
+       search_text = gtk_entry_get_text (GTK_ENTRY (selector->priv->search_entry));
+       if (search_text == NULL || search_text[0] == '\0')
+       {
+               return TRUE;
+       }
+
+       language = list_box_row_get_language (list_box_row);
+       g_return_val_if_fail (language != NULL, FALSE);
+
+       language_name = gtk_source_language_get_name (language);
+       g_return_val_if_fail (language_name != NULL, FALSE);
+
+       /* search_text is guaranteed to be UTF-8 (it comes from a GTK widget).
+        * language_name is not really, it can come from foreign input (*.lang
+        * file), so it's safer to check.
+        */
+       g_return_val_if_fail (g_utf8_validate (language_name, -1, NULL), FALSE);
+
+       language_name_normalized = g_utf8_normalize (language_name, -1, G_NORMALIZE_ALL);
+       language_name_casefolded = g_utf8_casefold (language_name_normalized, -1);
+       g_free (language_name_normalized);
+
+       /* Note: we do not apply g_strstrip() on the search text, because a
+        * trailing space (or - to a less extent - a leading space) can
+        * differentiate several GtkSourceLanguages, for example:
+        * - "ERB"
+        * - "ERB (HTML)"
+        * - "ERB (JavaScript)"
+        */
+       search_text_normalized = g_utf8_normalize (search_text, -1, G_NORMALIZE_ALL);
+       search_text_casefolded = g_utf8_casefold (search_text_normalized, -1);
+       g_free (search_text_normalized);
+
+       visible = strstr (language_name_casefolded, search_text_casefolded) != NULL;
+
+       g_free (language_name_casefolded);
+       g_free (search_text_casefolded);
+       return visible;
+}
+
+static void
+search_changed_cb (GtkSearchEntry            *search_entry,
+                  TeplHighlightModeSelector *selector)
+{
+       gtk_list_box_invalidate_filter (selector->priv->list_box);
+}
+
+static void
+list_box_row_activated_cb (GtkListBox                *list_box,
+                          GtkListBoxRow             *list_box_row,
+                          TeplHighlightModeSelector *selector)
+{
+       GtkSourceLanguage *language;
+
+       language = list_box_row_get_language (list_box_row);
+       g_return_if_fail (language != NULL);
+
+       g_object_ref (language);
+       g_signal_emit (selector, signals[SIGNAL_LANGUAGE_SELECTED], 0, language);
+       g_object_unref (language);
+}
+
+static void
+tepl_highlight_mode_selector_init (TeplHighlightModeSelector *selector)
+{
+       GtkWidget *scrolled_window;
+
+       selector->priv = tepl_highlight_mode_selector_get_instance_private (selector);
+
+       gtk_orientable_set_orientation (GTK_ORIENTABLE (selector), GTK_ORIENTATION_VERTICAL);
+
+       selector->priv->search_entry = GTK_SEARCH_ENTRY (gtk_search_entry_new ());
+       gtk_widget_show (GTK_WIDGET (selector->priv->search_entry));
+       gtk_container_add (GTK_CONTAINER (selector), GTK_WIDGET (selector->priv->search_entry));
+
+       selector->priv->list_box = GTK_LIST_BOX (gtk_list_box_new ());
+       gtk_list_box_set_activate_on_single_click (selector->priv->list_box, FALSE);
+       populate_list_box (selector);
+       gtk_widget_set_hexpand (GTK_WIDGET (selector->priv->list_box), TRUE);
+       gtk_widget_set_vexpand (GTK_WIDGET (selector->priv->list_box), TRUE);
+
+       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+       gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (selector->priv->list_box));
+       gtk_widget_show_all (scrolled_window);
+       gtk_container_add (GTK_CONTAINER (selector), scrolled_window);
+
+       gtk_list_box_set_filter_func (selector->priv->list_box,
+                                     filter_cb,
+                                     selector,
+                                     NULL);
+
+       g_signal_connect (selector->priv->search_entry,
+                         "search-changed",
+                         G_CALLBACK (search_changed_cb),
+                         selector);
+
+       g_signal_connect (selector->priv->list_box,
+                         "row-activated",
+                         G_CALLBACK (list_box_row_activated_cb),
+                         selector);
+}
+
+/**
+ * tepl_highlight_mode_selector_new:
+ *
+ * Returns: (transfer floating): a new #TeplHighlightModeSelector widget.
+ * Since: 5.2
+ */
+TeplHighlightModeSelector *
+tepl_highlight_mode_selector_new (void)
+{
+       return g_object_new (TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR, NULL);
+}
diff --git a/tepl/tepl-highlight-mode-selector.h b/tepl/tepl-highlight-mode-selector.h
new file mode 100644
index 0000000..57b3d40
--- /dev/null
+++ b/tepl/tepl-highlight-mode-selector.h
@@ -0,0 +1,55 @@
+/* SPDX-FileCopyrightText: 2020 - Sébastien Wilmet <swilmet gnome org>
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+
+#ifndef TEPL_HIGHLIGHT_MODE_SELECTOR_H
+#define TEPL_HIGHLIGHT_MODE_SELECTOR_H
+
+#if !defined (TEPL_H_INSIDE) && !defined (TEPL_COMPILATION)
+#error "Only <tepl/tepl.h> can be included directly."
+#endif
+
+#include <gtksourceview/gtksource.h>
+#include <tepl/tepl-macros.h>
+
+G_BEGIN_DECLS
+
+#define TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR             (tepl_highlight_mode_selector_get_type ())
+#define TEPL_HIGHLIGHT_MODE_SELECTOR(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR, TeplHighlightModeSelector))
+#define TEPL_HIGHLIGHT_MODE_SELECTOR_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR, TeplHighlightModeSelectorClass))
+#define TEPL_IS_HIGHLIGHT_MODE_SELECTOR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR))
+#define TEPL_IS_HIGHLIGHT_MODE_SELECTOR_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR))
+#define TEPL_HIGHLIGHT_MODE_SELECTOR_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
TEPL_TYPE_HIGHLIGHT_MODE_SELECTOR, TeplHighlightModeSelectorClass))
+
+typedef struct _TeplHighlightModeSelector         TeplHighlightModeSelector;
+typedef struct _TeplHighlightModeSelectorClass    TeplHighlightModeSelectorClass;
+typedef struct _TeplHighlightModeSelectorPrivate  TeplHighlightModeSelectorPrivate;
+
+struct _TeplHighlightModeSelector
+{
+       GtkGrid parent;
+
+       TeplHighlightModeSelectorPrivate *priv;
+};
+
+struct _TeplHighlightModeSelectorClass
+{
+       GtkGridClass parent_class;
+
+       /* Signals */
+       void (* language_selected)      (TeplHighlightModeSelector *selector,
+                                        GtkSourceLanguage         *language);
+
+       gpointer padding[12];
+};
+
+_TEPL_EXTERN
+GType          tepl_highlight_mode_selector_get_type   (void);
+
+_TEPL_EXTERN
+TeplHighlightModeSelector *
+               tepl_highlight_mode_selector_new        (void);
+
+G_END_DECLS
+
+#endif /* TEPL_HIGHLIGHT_MODE_SELECTOR_H */
diff --git a/tepl/tepl.h b/tepl/tepl.h
index f2751b0..b6368b1 100644
--- a/tepl/tepl.h
+++ b/tepl/tepl.h
@@ -23,6 +23,7 @@
 #include <tepl/tepl-fold-region.h>
 #include <tepl/tepl-goto-line-bar.h>
 #include <tepl/tepl-gutter-renderer-folds.h>
+#include <tepl/tepl-highlight-mode-selector.h>
 #include <tepl/tepl-info-bar.h>
 #include <tepl/tepl-init.h>
 #include <tepl/tepl-io-error-info-bars.h>


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