[gnome-builder] plugins/editorui: create scheme selector widget
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins/editorui: create scheme selector widget
- Date: Fri, 12 Aug 2022 21:42:01 +0000 (UTC)
commit 2283bbc20338519df7ea356a863c02f042f6bf7f
Author: Christian Hergert <chergert redhat com>
Date: Fri Aug 12 14:41:54 2022 -0700
plugins/editorui: create scheme selector widget
This has a lot of the color/sorting stuff from g-t-e copied over as well,
which will eventually fix #1747 when the new IdeTweaks engine lands.
src/plugins/editorui/editorui.gresource.xml | 1 +
.../editorui/gbp-editorui-scheme-selector.c | 294 +++++++++++++++++++++
.../editorui/gbp-editorui-scheme-selector.h | 31 +++
.../editorui/gbp-editorui-scheme-selector.ui | 20 ++
src/plugins/editorui/gbp-editorui-tweaks-addin.c | 41 ++-
src/plugins/editorui/meson.build | 1 +
src/plugins/editorui/style.css | 3 +
src/plugins/editorui/tweaks.ui | 5 +
8 files changed, 382 insertions(+), 14 deletions(-)
---
diff --git a/src/plugins/editorui/editorui.gresource.xml b/src/plugins/editorui/editorui.gresource.xml
index d9f1fd160..990567891 100644
--- a/src/plugins/editorui/editorui.gresource.xml
+++ b/src/plugins/editorui/editorui.gresource.xml
@@ -6,6 +6,7 @@
<file>gtk/keybindings.json</file>
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
<file preprocess="xml-stripblanks">gbp-editorui-position-label.ui</file>
+ <file preprocess="xml-stripblanks">gbp-editorui-scheme-selector.ui</file>
<file preprocess="xml-stripblanks">tweaks.ui</file>
</gresource>
</gresources>
diff --git a/src/plugins/editorui/gbp-editorui-scheme-selector.c
b/src/plugins/editorui/gbp-editorui-scheme-selector.c
new file mode 100644
index 000000000..7f968117c
--- /dev/null
+++ b/src/plugins/editorui/gbp-editorui-scheme-selector.c
@@ -0,0 +1,294 @@
+/* gbp-editorui-scheme-selector.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-editorui-scheme-selector"
+
+#include "config.h"
+
+#include <libide-gui.h>
+#include <libide-sourceview.h>
+
+#include "gbp-editorui-scheme-selector.h"
+
+struct _GbpEditoruiSchemeSelector
+{
+ GtkWidget parent_instance;
+
+ GtkFlowBox *flow_box;
+ GSettings *settings;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (GbpEditoruiSchemeSelector, gbp_editorui_scheme_selector, GTK_TYPE_WIDGET)
+
+static GParamSpec *properties [N_PROPS];
+
+typedef struct
+{
+ const char *id;
+ const char *sort_key;
+ GtkSourceStyleScheme *scheme;
+ guint has_alt : 1;
+ guint is_dark : 1;
+} SchemeInfo;
+
+static int
+sort_schemes_cb (gconstpointer a,
+ gconstpointer b)
+{
+ const SchemeInfo *info_a = a;
+ const SchemeInfo *info_b = b;
+
+ /* Light schemes first */
+ if (!info_a->is_dark && info_b->is_dark)
+ return -1;
+ else if (info_a->is_dark && !info_b->is_dark)
+ return 1;
+
+ /* Items with variants first */
+ if (info_a->has_alt && !info_b->has_alt)
+ return -1;
+ else if (!info_a->has_alt && info_b->has_alt)
+ return 1;
+
+ return g_utf8_collate (info_a->sort_key, info_b->sort_key);
+}
+
+static void
+update_style_scheme_selection (GtkFlowBox *flow_box)
+{
+ const char *id;
+
+ g_assert (GTK_IS_FLOW_BOX (flow_box));
+
+ id = ide_application_get_style_scheme (IDE_APPLICATION_DEFAULT);
+
+ for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (flow_box));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ GtkFlowBoxChild *intermediate = GTK_FLOW_BOX_CHILD (child);
+ GtkSourceStyleSchemePreview *preview = GTK_SOURCE_STYLE_SCHEME_PREVIEW (gtk_flow_box_child_get_child
(intermediate));
+ GtkSourceStyleScheme *scheme = gtk_source_style_scheme_preview_get_scheme (preview);
+ const char *scheme_id = gtk_source_style_scheme_get_id (scheme);
+ gboolean selected = g_strcmp0 (scheme_id, id) == 0;
+
+ gtk_source_style_scheme_preview_set_selected (preview, selected);
+ }
+}
+
+static void
+update_style_schemes (GtkFlowBox *flow_box)
+{
+ GtkSourceStyleSchemeManager *sm;
+ const char * const *scheme_ids;
+ g_autoptr(GArray) schemes = NULL;
+ const char *current_scheme;
+ gboolean is_dark;
+ guint j = 0;
+ GtkWidget *child;
+
+ g_assert (GTK_IS_FLOW_BOX (flow_box));
+
+ schemes = g_array_new (FALSE, FALSE, sizeof (SchemeInfo));
+ is_dark = adw_style_manager_get_dark (adw_style_manager_get_default ());
+ current_scheme = ide_application_get_style_scheme (IDE_APPLICATION_DEFAULT);
+
+ /* Populate schemes for preferences */
+ sm = gtk_source_style_scheme_manager_get_default ();
+ scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (sm);
+
+ for (guint i = 0; scheme_ids[i]; i++)
+ {
+ SchemeInfo info;
+
+ /* Ignore our printing scheme */
+ if (g_strcmp0 (scheme_ids[i], "printing") == 0)
+ continue;
+
+ info.scheme = gtk_source_style_scheme_manager_get_scheme (sm, scheme_ids[i]);
+ info.id = gtk_source_style_scheme_get_id (info.scheme);
+ info.sort_key = gtk_source_style_scheme_get_name (info.scheme);
+ info.has_alt = FALSE;
+ info.is_dark = FALSE;
+
+ if (ide_source_style_scheme_is_dark (info.scheme))
+ {
+ GtkSourceStyleScheme *alt = ide_source_style_scheme_get_variant (info.scheme, "light");
+
+ g_assert (GTK_SOURCE_IS_STYLE_SCHEME (alt));
+
+ if (alt != info.scheme)
+ {
+ info.sort_key = gtk_source_style_scheme_get_id (alt);
+ info.has_alt = TRUE;
+ }
+
+ info.is_dark = TRUE;
+ }
+ else
+ {
+ GtkSourceStyleScheme *alt = ide_source_style_scheme_get_variant (info.scheme, "dark");
+
+ g_assert (GTK_SOURCE_IS_STYLE_SCHEME (alt));
+
+ if (alt != info.scheme)
+ info.has_alt = TRUE;
+ }
+
+ g_array_append_val (schemes, info);
+ }
+
+ g_array_sort (schemes, sort_schemes_cb);
+
+ while ((child = gtk_widget_get_first_child (GTK_WIDGET (flow_box))))
+ gtk_flow_box_remove (flow_box, child);
+
+ for (guint i = 0; i < schemes->len; i++)
+ {
+ const SchemeInfo *info = &g_array_index (schemes, SchemeInfo, i);
+ GtkWidget *preview;
+
+ /* Ignore if not matching light/dark variant for app, unless it is
+ * the current scheme and it has no alternate.
+ */
+ if (is_dark != ide_source_style_scheme_is_dark (info->scheme) &&
+ (g_strcmp0 (info->id, current_scheme) != 0 || info->has_alt))
+ continue;
+
+ preview = gtk_source_style_scheme_preview_new (info->scheme);
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (preview), "app.style-scheme-name");
+ gtk_actionable_set_action_target (GTK_ACTIONABLE (preview), "s", info->id);
+ gtk_flow_box_insert (flow_box, preview, -1);
+
+ j++;
+ }
+
+ update_style_scheme_selection (flow_box);
+}
+
+static void
+style_scheme_activated_cb (GbpEditoruiSchemeSelector *self,
+ GtkFlowBoxChild *child,
+ GtkFlowBox *flow_box)
+{
+ GtkWidget *preview;
+
+ g_assert (GBP_IS_EDITORUI_SCHEME_SELECTOR (self));
+ g_assert (GTK_IS_FLOW_BOX_CHILD (child));
+ g_assert (GTK_IS_FLOW_BOX (flow_box));
+
+ if ((preview = gtk_flow_box_child_get_child (child)))
+ gtk_widget_activate (preview);
+}
+
+static void
+gbp_editorui_scheme_selector_constructed (GObject *object)
+{
+ GbpEditoruiSchemeSelector *self = (GbpEditoruiSchemeSelector *)object;
+
+ G_OBJECT_CLASS (gbp_editorui_scheme_selector_parent_class)->constructed (object);
+
+ update_style_schemes (self->flow_box);
+}
+
+static void
+gbp_editorui_scheme_selector_dispose (GObject *object)
+{
+ GbpEditoruiSchemeSelector *self = (GbpEditoruiSchemeSelector *)object;
+
+ g_clear_pointer ((GtkWidget **)&self->flow_box, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (gbp_editorui_scheme_selector_parent_class)->dispose (object);
+}
+
+static void
+gbp_editorui_scheme_selector_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpEditoruiSchemeSelector *self = GBP_EDITORUI_SCHEME_SELECTOR (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_editorui_scheme_selector_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpEditoruiSchemeSelector *self = GBP_EDITORUI_SCHEME_SELECTOR (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_editorui_scheme_selector_class_init (GbpEditoruiSchemeSelectorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = gbp_editorui_scheme_selector_constructed;
+ object_class->dispose = gbp_editorui_scheme_selector_dispose;
+ object_class->get_property = gbp_editorui_scheme_selector_get_property;
+ object_class->set_property = gbp_editorui_scheme_selector_set_property;
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+ gtk_widget_class_set_template_from_resource (widget_class,
"/plugins/editorui/gbp-editorui-scheme-selector.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpEditoruiSchemeSelector, flow_box);
+ gtk_widget_class_bind_template_child (widget_class, GbpEditoruiSchemeSelector, settings);
+ gtk_widget_class_bind_template_callback (widget_class, style_scheme_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, update_style_scheme_selection);
+}
+
+static void
+gbp_editorui_scheme_selector_init (GbpEditoruiSchemeSelector *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect_object (IDE_APPLICATION_DEFAULT,
+ "notify::style-scheme",
+ G_CALLBACK (update_style_scheme_selection),
+ self->flow_box,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (adw_style_manager_get_default (),
+ "notify::dark",
+ G_CALLBACK (update_style_schemes),
+ self->flow_box,
+ G_CONNECT_SWAPPED);
+
+ /* Ensure we've queried style-scheme-name once */
+ g_variant_unref (g_settings_get_value (self->settings, "style-scheme-name"));
+}
diff --git a/src/plugins/editorui/gbp-editorui-scheme-selector.h
b/src/plugins/editorui/gbp-editorui-scheme-selector.h
new file mode 100644
index 000000000..139536f4d
--- /dev/null
+++ b/src/plugins/editorui/gbp-editorui-scheme-selector.h
@@ -0,0 +1,31 @@
+/* gbp-editorui-scheme-selector.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_EDITORUI_SCHEME_SELECTOR (gbp_editorui_scheme_selector_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpEditoruiSchemeSelector, gbp_editorui_scheme_selector, GBP,
EDITORUI_SCHEME_SELECTOR, GtkWidget)
+
+G_END_DECLS
diff --git a/src/plugins/editorui/gbp-editorui-scheme-selector.ui
b/src/plugins/editorui/gbp-editorui-scheme-selector.ui
new file mode 100644
index 000000000..26011f795
--- /dev/null
+++ b/src/plugins/editorui/gbp-editorui-scheme-selector.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpEditoruiSchemeSelector" parent="GtkWidget">
+ <child>
+ <object class="GtkFlowBox" id="flow_box">
+ <signal name="child-activated" handler="style_scheme_activated_cb" swapped="true"
object="GbpEditoruiSchemeSelector"/>
+ <property name="hexpand">true</property>
+ <property name="column-spacing">8</property>
+ <property name="row-spacing">8</property>
+ <property name="max-children-per-line">4</property>
+ <property name="max-children-per-line">4</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </child>
+ </template>
+ <object class="GSettings" id="settings">
+ <property name="schema-id">org.gnome.builder.editor</property>
+ <signal name="changed::style-scheme-name" handler="update_style_scheme_selection" object="flow_box"
swapped="true"/>
+ </object>
+</interface>
diff --git a/src/plugins/editorui/gbp-editorui-tweaks-addin.c
b/src/plugins/editorui/gbp-editorui-tweaks-addin.c
index 230b80773..b74cd3ea0 100644
--- a/src/plugins/editorui/gbp-editorui-tweaks-addin.c
+++ b/src/plugins/editorui/gbp-editorui-tweaks-addin.c
@@ -22,7 +22,10 @@
#include "config.h"
+#include <libide-gui.h>
+
#include "gbp-editorui-preview.h"
+#include "gbp-editorui-scheme-selector.h"
#include "gbp-editorui-tweaks-addin.h"
struct _GbpEditoruiTweaksAddin
@@ -32,27 +35,35 @@ struct _GbpEditoruiTweaksAddin
G_DEFINE_FINAL_TYPE (GbpEditoruiTweaksAddin, gbp_editorui_tweaks_addin, IDE_TYPE_TWEAKS_ADDIN)
+static GtkWidget *
+editorui_create_style_scheme_preview (GbpEditoruiTweaksAddin *self,
+ IdeTweaksWidget *widget)
+{
+ g_assert (GBP_IS_EDITORUI_TWEAKS_ADDIN (self));
+ g_assert (IDE_IS_TWEAKS_WIDGET (widget));
+
+ return g_object_new (GBP_TYPE_EDITORUI_PREVIEW,
+ "bottom-margin", 8,
+ "css-classes", IDE_STRV_INIT ("card"),
+ "cursor-visible", FALSE,
+ "left-margin", 12,
+ "monospace", TRUE,
+ "right-margin", 12,
+ "right-margin-position", 30,
+ "top-margin", 8,
+ NULL);
+}
+
static GtkWidget *
editorui_create_style_scheme_selector (GbpEditoruiTweaksAddin *self,
IdeTweaksWidget *widget)
{
- GbpEditoruiPreview *preview;
- GtkBox *box;
-
g_assert (GBP_IS_EDITORUI_TWEAKS_ADDIN (self));
g_assert (IDE_IS_TWEAKS_WIDGET (widget));
- box = g_object_new (GTK_TYPE_BOX,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "spacing", 12,
- "margin-bottom", 12,
- NULL);
- preview = g_object_new (GBP_TYPE_EDITORUI_PREVIEW,
- "css-classes", IDE_STRV_INIT ("card"),
- NULL);
- gtk_box_append (box, GTK_WIDGET (preview));
-
- return GTK_WIDGET (box);
+ return g_object_new (GBP_TYPE_EDITORUI_SCHEME_SELECTOR,
+ "margin-top", 18,
+ NULL);
}
static void
@@ -65,6 +76,8 @@ gbp_editorui_tweaks_addin_init (GbpEditoruiTweaksAddin *self)
{
ide_tweaks_addin_set_resource_path (IDE_TWEAKS_ADDIN (self),
"/plugins/editorui/tweaks.ui");
+ ide_tweaks_addin_bind_callback (IDE_TWEAKS_ADDIN (self),
+ editorui_create_style_scheme_preview);
ide_tweaks_addin_bind_callback (IDE_TWEAKS_ADDIN (self),
editorui_create_style_scheme_selector);
}
diff --git a/src/plugins/editorui/meson.build b/src/plugins/editorui/meson.build
index 6444f5cb0..5c1888237 100644
--- a/src/plugins/editorui/meson.build
+++ b/src/plugins/editorui/meson.build
@@ -4,6 +4,7 @@ plugins_sources += files([
'gbp-editorui-position-label.c',
'gbp-editorui-preferences-addin.c',
'gbp-editorui-preview.c',
+ 'gbp-editorui-scheme-selector.c',
'gbp-editorui-tweaks-addin.c',
'gbp-editorui-workbench-addin.c',
'gbp-editorui-workspace-addin.c',
diff --git a/src/plugins/editorui/style.css b/src/plugins/editorui/style.css
index 2bce7c332..b26fe22da 100644
--- a/src/plugins/editorui/style.css
+++ b/src/plugins/editorui/style.css
@@ -1,12 +1,15 @@
+.IdeTweaksWindow preferencesgroup flowbox.style-schemes flowboxchild,
window.preferences preferencesgroup flowbox.style-schemes flowboxchild {
outline-offset: 2px;
border-radius: 12px;
outline-width: 2px;
padding: 0;
}
+.IdeTweaksWindow preferencesgroup flowbox.style-schemes flowboxchild GtkSourceStyleSchemePreview,
window.preferences preferencesgroup flowbox.style-schemes flowboxchild GtkSourceStyleSchemePreview {
margin: 0;
}
+.IdeTweaksWindow preferencesgroup flowbox.style-schemes flowboxchild
GtkSourceStyleSchemePreview:not(.selected),
window.preferences preferencesgroup flowbox.style-schemes flowboxchild
GtkSourceStyleSchemePreview:not(.selected) {
box-shadow: 0 0 0 1px alpha(black, 0.03),
0 1px 3px 1px alpha(black, .07),
diff --git a/src/plugins/editorui/tweaks.ui b/src/plugins/editorui/tweaks.ui
index 46370bd80..c723feb76 100644
--- a/src/plugins/editorui/tweaks.ui
+++ b/src/plugins/editorui/tweaks.ui
@@ -8,6 +8,11 @@
<child>
<object class="IdeTweaksGroup" id="appearance_page_color_group">
<property name="title" translatable="yes">Color</property>
+ <child>
+ <object class="IdeTweaksWidget" id="style_scheme_preview">
+ <signal name="create" handler="editorui_create_style_scheme_preview"
object="GbpEditoruiTweaksAddin" swapped="true"/>
+ </object>
+ </child>
<child>
<object class="IdeTweaksWidget" id="style_scheme_selector">
<signal name="create" handler="editorui_create_style_scheme_selector"
object="GbpEditoruiTweaksAddin" swapped="true"/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]