/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- * * This file is part of GtkSourceView * * Copyright (C) 2014 - Christian Hergert * Copyright (C) 2014 - Ignacio Casal Quinteiro * * GtkSourceView is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * GtkSourceView 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with GtkSourceView. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include "gtksourcestyleschemechooserwidget.h" #include "gtksourcestyleschemechooser.h" #include "gtksourcestylescheme.h" #include "gtksourcestyleschememanager.h" #include "gtksourcelanguage.h" #include "gtksourcelanguagemanager.h" #include "gtksourcebuffer.h" #include "gtksourceview.h" /** * SECTION:styleschemechooserwidget * @Short_description: A widget for choosing style schemes * @Title: GtkSourceStyleSchemeChooserWidget * @See_also: #GtkSourceStyleSchemeChooserButton * * The #GtkSourceStyleSchemeChooserWidget widget lets the user select a * style scheme. By default, the chooser presents a predefined list * of style schemes. * * To change the initially selected style scheme, * use gtk_source_style_scheme_chooser_set_style_scheme(). * To get the selected style scheme * use gtk_source_style_scheme_chooser_get_style_scheme(). * * Since: 3.16 */ typedef struct { GtkListBox *list_box; GtkSourceStyleScheme *scheme; } GtkSourceStyleSchemeChooserWidgetPrivate; static void gtk_source_style_scheme_chooser_widget_style_scheme_chooser_interface_init (GtkSourceStyleSchemeChooserInterface *iface); G_DEFINE_TYPE_WITH_CODE (GtkSourceStyleSchemeChooserWidget, gtk_source_style_scheme_chooser_widget, GTK_TYPE_BIN, G_ADD_PRIVATE (GtkSourceStyleSchemeChooserWidget) G_IMPLEMENT_INTERFACE (GTK_SOURCE_TYPE_STYLE_SCHEME_CHOOSER, gtk_source_style_scheme_chooser_widget_style_scheme_chooser_interface_init)) #define GET_PRIV(o) gtk_source_style_scheme_chooser_widget_get_instance_private (o) enum { PROP_0, PROP_STYLE_SCHEME }; static void gtk_source_style_scheme_chooser_widget_dispose (GObject *object) { GtkSourceStyleSchemeChooserWidget *widget = GTK_SOURCE_STYLE_SCHEME_CHOOSER_WIDGET (object); GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); g_clear_object (&priv->scheme); G_OBJECT_CLASS (gtk_source_style_scheme_chooser_widget_parent_class)->dispose (object); } static void gtk_source_style_scheme_chooser_widget_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_STYLE_SCHEME: g_value_set_object (value, gtk_source_style_scheme_chooser_get_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gtk_source_style_scheme_chooser_widget_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_STYLE_SCHEME: gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (object), g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gtk_source_style_scheme_chooser_widget_class_init (GtkSourceStyleSchemeChooserWidgetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = gtk_source_style_scheme_chooser_widget_dispose; object_class->get_property = gtk_source_style_scheme_chooser_widget_get_property; object_class->set_property = gtk_source_style_scheme_chooser_widget_set_property; g_object_class_override_property (object_class, PROP_STYLE_SCHEME, "style-scheme"); } static GtkWidget * make_row (GtkSourceStyleScheme *scheme, GtkSourceLanguage *language) { GtkWidget *row; AtkObject *accessible; GtkWidget *event; GtkSourceBuffer *buffer; GtkWidget *view; gchar *text; row = gtk_list_box_row_new (); accessible = gtk_widget_get_accessible (row); atk_object_set_name (accessible, gtk_source_style_scheme_get_name (scheme)); gtk_widget_show (row); g_object_set_data (G_OBJECT (row), "scheme", scheme); event = gtk_event_box_new (); gtk_event_box_set_above_child (GTK_EVENT_BOX (event), TRUE); gtk_widget_show (event); gtk_container_add (GTK_CONTAINER (row), event); buffer = gtk_source_buffer_new_with_language (language); gtk_source_buffer_set_highlight_matching_brackets (buffer, FALSE); gtk_source_buffer_set_style_scheme (buffer, scheme); text = g_strdup_printf ("/* %s */\n#include ", gtk_source_style_scheme_get_name (scheme)); gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), text, -1); g_free (text); view = g_object_new (GTK_SOURCE_TYPE_VIEW, "buffer", buffer, "can-focus", FALSE, "cursor-visible", FALSE, "editable", FALSE, "visible", TRUE, "show-line-numbers", TRUE, "right-margin-position", 30, "show-right-margin", TRUE, "margin", 2, NULL); gtk_container_add (GTK_CONTAINER (event), view); return row; } static void on_row_selected (GtkListBox *list_box, GtkListBoxRow *row, GtkSourceStyleSchemeChooserWidget *widget) { GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); if (row != NULL) { GtkSourceStyleScheme *scheme; scheme = g_object_get_data (G_OBJECT (row), "scheme"); if (g_set_object (&priv->scheme, scheme)) { g_object_notify (G_OBJECT (widget), "style-scheme"); } } } static void gtk_source_style_scheme_chooser_widget_populate (GtkSourceStyleSchemeChooserWidget *widget) { GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); GtkSourceLanguageManager *lm; GtkSourceLanguage *lang; GtkSourceStyleSchemeManager *manager; const gchar * const *scheme_ids; guint i; gboolean row_selected = FALSE; g_signal_handlers_block_by_func (priv->list_box, on_row_selected, widget); gtk_container_foreach (GTK_CONTAINER (priv->list_box), (GtkCallback)gtk_widget_destroy, NULL); manager = gtk_source_style_scheme_manager_get_default (); scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (manager); lm = gtk_source_language_manager_get_default (); lang = gtk_source_language_manager_get_language (lm, "c"); for (i = 0; scheme_ids [i]; i++) { GtkWidget *row; GtkSourceStyleScheme *scheme; scheme = gtk_source_style_scheme_manager_get_scheme (manager, scheme_ids [i]); row = make_row (scheme, lang); gtk_container_add (GTK_CONTAINER (priv->list_box), GTK_WIDGET (row)); if (scheme == priv->scheme) { gtk_list_box_select_row (priv->list_box, GTK_LIST_BOX_ROW (row)); row_selected = TRUE; } } g_signal_handlers_unblock_by_func (priv->list_box, on_row_selected, widget); /* The current scheme may have been removed so select the default one */ if (!row_selected) { gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (widget), _gtk_source_style_scheme_get_default ()); } } static void on_scheme_ids_changed (GtkSourceStyleSchemeManager *manager, GParamSpec *pspec, GtkSourceStyleSchemeChooserWidget *widget) { gtk_source_style_scheme_chooser_widget_populate (widget); } static void gtk_source_style_scheme_chooser_widget_init (GtkSourceStyleSchemeChooserWidget *widget) { GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); GtkSourceStyleSchemeManager *manager; priv->list_box = GTK_LIST_BOX (gtk_list_box_new ()); gtk_list_box_set_selection_mode (priv->list_box, GTK_SELECTION_BROWSE); gtk_widget_show (GTK_WIDGET (priv->list_box)); gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (priv->list_box)); manager = gtk_source_style_scheme_manager_get_default (); g_signal_connect (manager, "notify::scheme-ids", G_CALLBACK (on_scheme_ids_changed), widget); gtk_source_style_scheme_chooser_widget_populate (widget); gtk_source_style_scheme_chooser_set_style_scheme (GTK_SOURCE_STYLE_SCHEME_CHOOSER (widget), _gtk_source_style_scheme_get_default ()); g_signal_connect (priv->list_box, "row-selected", G_CALLBACK (on_row_selected), widget); } static GtkSourceStyleScheme * gtk_source_style_scheme_chooser_widget_get_style_scheme (GtkSourceStyleSchemeChooser *chooser) { GtkSourceStyleSchemeChooserWidget *widget = GTK_SOURCE_STYLE_SCHEME_CHOOSER_WIDGET (chooser); GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); return priv->scheme; } static void gtk_source_style_scheme_chooser_widget_set_style_scheme (GtkSourceStyleSchemeChooser *chooser, GtkSourceStyleScheme *scheme) { GtkSourceStyleSchemeChooserWidget *widget = GTK_SOURCE_STYLE_SCHEME_CHOOSER_WIDGET (chooser); GtkSourceStyleSchemeChooserWidgetPrivate *priv = GET_PRIV (widget); if (g_set_object (&priv->scheme, scheme)) { GList *children; GList *l; children = gtk_container_get_children (GTK_CONTAINER (priv->list_box)); for (l = children; l != NULL; l = g_list_next (l)) { GtkListBoxRow *row = l->data; GtkSourceStyleScheme *cur; cur = g_object_get_data (G_OBJECT (row), "scheme"); if (cur == scheme) { g_signal_handlers_block_by_func (priv->list_box, on_row_selected, widget); gtk_list_box_select_row (priv->list_box, row); g_signal_handlers_unblock_by_func (priv->list_box, on_row_selected, widget); break; } } g_list_free (children); g_object_notify (G_OBJECT (chooser), "style-scheme"); } } static void gtk_source_style_scheme_chooser_widget_style_scheme_chooser_interface_init (GtkSourceStyleSchemeChooserInterface *iface) { iface->get_style_scheme = gtk_source_style_scheme_chooser_widget_get_style_scheme; iface->set_style_scheme = gtk_source_style_scheme_chooser_widget_set_style_scheme; } /** * gtk_source_style_scheme_chooser_widget_new: * * Creates a new #GtkSourceStyleSchemeChooserWidget. * * Returns: a new #GtkSourceStyleSchemeChooserWidget. * * Since: 3.16 */ GtkWidget * gtk_source_style_scheme_chooser_widget_new (void) { return g_object_new (GTK_SOURCE_TYPE_STYLE_SCHEME_CHOOSER_WIDGET, NULL); }