/* * glade-gtk-cell-renderer.c - GladeWidgetAdaptor for GtkCellRenderer * * Copyright (C) 2013 Tristan Van Berkom * * Authors: * Tristan Van Berkom * * This library 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. * * This library 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "glade-gtk-image.h" /* For GtkIconSize serialization */ #include "glade-gtk-tree-view.h" #include "glade-gtk-cell-renderer.h" #include "glade-cell-renderer-editor.h" #include "glade-column-types.h" void glade_gtk_cell_renderer_action_activate (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *action_path) { if (strcmp (action_path, "launch_editor") == 0) { GladeWidget *w = glade_widget_get_from_gobject (object); while ((w = glade_widget_get_parent (w))) { GObject *object = glade_widget_get_object (w); if (GTK_IS_TREE_VIEW (object)) { glade_gtk_treeview_launch_editor (object); break; } } } else GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->action_activate (adaptor, object, action_path); } void glade_gtk_cell_renderer_deep_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladePropertyDef *pdef; GladeProperty *property; GladeWidget *widget; const GList *l; widget = glade_widget_get_from_gobject (object); for (l = glade_widget_adaptor_get_properties (adaptor); l; l = l->next) { pdef = l->data; if (strncmp (glade_property_def_id (pdef), "use-attr-", strlen ("use-attr-")) == 0) { property = glade_widget_get_property (widget, glade_property_def_id (pdef)); glade_property_sync (property); } } g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes, object); } GladeEditorProperty * glade_gtk_cell_renderer_create_eprop (GladeWidgetAdaptor *adaptor, GladePropertyDef *def, gboolean use_command) { GladeEditorProperty *eprop; if (strncmp (glade_property_def_id (def), "attr-", strlen ("attr-")) == 0) eprop = g_object_new (GLADE_TYPE_EPROP_CELL_ATTRIBUTE, "property-def", def, "use-command", use_command, NULL); else eprop = GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->create_eprop (adaptor, def, use_command); return eprop; } GladeEditable * glade_gtk_cell_renderer_create_editable (GladeWidgetAdaptor *adaptor, GladeEditorPageType type) { GladeEditable *editable; /* Get base editable */ editable = GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type); if (type == GLADE_PAGE_GENERAL || type == GLADE_PAGE_COMMON) return (GladeEditable *) glade_cell_renderer_editor_new (adaptor, type, editable); return editable; } static void glade_gtk_cell_renderer_set_use_attribute (GObject *object, const gchar *property_name, const GValue *value) { GladeWidget *widget = glade_widget_get_from_gobject (object); gchar *attr_prop_name, *prop_msg, *attr_msg; attr_prop_name = g_strdup_printf ("attr-%s", property_name); prop_msg = g_strdup_printf (_("%s is set to load %s from the model"), glade_widget_get_name (widget), property_name); attr_msg = g_strdup_printf (_("%s is set to manipulate %s directly"), glade_widget_get_name (widget), attr_prop_name); glade_widget_property_set_sensitive (widget, property_name, FALSE, prop_msg); glade_widget_property_set_sensitive (widget, attr_prop_name, FALSE, attr_msg); if (g_value_get_boolean (value)) glade_widget_property_set_sensitive (widget, attr_prop_name, TRUE, NULL); else { GladeProperty *property = glade_widget_get_property (widget, property_name); glade_property_set_sensitive (property, TRUE, NULL); glade_property_sync (property); } g_free (prop_msg); g_free (attr_msg); g_free (attr_prop_name); } static GladeProperty * glade_gtk_cell_renderer_attribute_switch (GladeWidget *gwidget, const gchar *property_name) { GladeProperty *property; gchar *use_attr_name = g_strdup_printf ("use-attr-%s", property_name); property = glade_widget_get_property (gwidget, use_attr_name); g_free (use_attr_name); return property; } static gboolean glade_gtk_cell_renderer_property_enabled (GObject *object, const gchar *property_name) { GladeProperty *property; GladeWidget *gwidget = glade_widget_get_from_gobject (object); gboolean use_attr = TRUE; if ((property = glade_gtk_cell_renderer_attribute_switch (gwidget, property_name)) != NULL) glade_property_get (property, &use_attr); return !use_attr; } void glade_gtk_cell_renderer_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *property_name, const GValue *value) { static gint use_attr_len = 0; static gint attr_len = 0; if (!attr_len) { use_attr_len = strlen ("use-attr-"); attr_len = strlen ("attr-"); } if (strncmp (property_name, "use-attr-", use_attr_len) == 0) glade_gtk_cell_renderer_set_use_attribute (object, &property_name[use_attr_len], value); else if (strncmp (property_name, "attr-", attr_len) == 0) glade_gtk_cell_renderer_sync_attributes (object); else if (glade_gtk_cell_renderer_property_enabled (object, property_name)) /* Chain Up */ GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->set_property (adaptor, object, property_name, value); } static void glade_gtk_cell_renderer_write_properties (GladeWidget *widget, GladeXmlContext *context, GladeXmlNode *node) { GladeProperty *property, *prop; GladePropertyDef *pdef; gchar *attr_name; GList *l; static gint attr_len = 0; if (!attr_len) attr_len = strlen ("attr-"); for (l = glade_widget_get_properties (widget); l; l = l->next) { property = l->data; pdef = glade_property_get_def (property); if (strncmp (glade_property_def_id (pdef), "attr-", attr_len) == 0) { gchar *use_attr_str; gboolean use_attr = FALSE; use_attr_str = g_strdup_printf ("use-%s", glade_property_def_id (pdef)); glade_widget_property_get (widget, use_attr_str, &use_attr); attr_name = (gchar *)&glade_property_def_id (pdef)[attr_len]; prop = glade_widget_get_property (widget, attr_name); if (!use_attr && prop) { /* Special case to write GtkCellRendererPixbuf:stock-size */ if (strcmp (attr_name, "stock-size") == 0) glade_gtk_write_icon_size (widget, context, node, "stock-size"); else glade_property_write (prop, context, node); } g_free (use_attr_str); } } } void glade_gtk_cell_renderer_write_widget (GladeWidgetAdaptor *adaptor, GladeWidget *widget, GladeXmlContext *context, GladeXmlNode *node) { if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) || glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE))) return; /* Write our normal properties, then chain up to write any other normal properties, * then attributes */ glade_gtk_cell_renderer_write_properties (widget, context, node); GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node); } static void glade_gtk_cell_renderer_parse_finished (GladeProject *project, GObject *object) { GladeWidget *widget = glade_widget_get_from_gobject (object); GladeProperty *property; GList *l; static gint attr_len = 0, use_attr_len = 0; /* Set "use-attr-*" everywhere that the object property is non-default * * We do this in the finished handler because some properties may be * object type properties (which may be anywhere in the glade file). */ if (!attr_len) { attr_len = strlen ("attr-"); use_attr_len = strlen ("use-attr-"); } for (l = glade_widget_get_properties (widget); l; l = l->next) { GladeProperty *switch_prop; GladePropertyDef *pdef; property = l->data; pdef = glade_property_get_def (property); if (strncmp (glade_property_def_id (pdef), "attr-", attr_len) != 0 && strncmp (glade_property_def_id (pdef), "use-attr-", use_attr_len) != 0 && (switch_prop = glade_gtk_cell_renderer_attribute_switch (widget, glade_property_def_id (pdef))) != NULL) { if (glade_property_original_default (property)) glade_property_set (switch_prop, TRUE); else glade_property_set (switch_prop, FALSE); } } } void glade_gtk_cell_renderer_read_widget (GladeWidgetAdaptor *adaptor, GladeWidget *widget, GladeXmlNode *node) { if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) || glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE))) return; /* First chain up and read in all the properties... */ GLADE_WIDGET_ADAPTOR_GET_ADAPTOR_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node); g_signal_connect_object (glade_widget_get_project (widget), "parse-finished", G_CALLBACK (glade_gtk_cell_renderer_parse_finished), glade_widget_get_object (widget), 0); } static gboolean glade_gtk_cell_layout_has_renderer (GtkCellLayout *layout, GtkCellRenderer *renderer) { GList *cells = gtk_cell_layout_get_cells (layout); gboolean has_renderer; has_renderer = (g_list_find (cells, renderer) != NULL); g_list_free (cells); return has_renderer; } gboolean glade_gtk_cell_renderer_sync_attributes (GObject *object) { GtkCellLayout *layout; GtkCellRenderer *cell; GladeWidget *widget; GladeWidget *parent; GladeWidget *gmodel; GladeProperty *property; GladePropertyDef *pdef; gchar *attr_prop_name; GList *l, *column_list = NULL; gint columns = 0; static gint attr_len = 0; if (!attr_len) attr_len = strlen ("attr-"); /* Apply attributes to renderer when bound to a model in runtime */ widget = glade_widget_get_from_gobject (object); parent = glade_widget_get_parent (widget); if (parent == NULL) return FALSE; /* When creating widgets, sometimes the parent is set before parenting happens, * here we have to be careful for that.. */ layout = GTK_CELL_LAYOUT (glade_widget_get_object (parent)); cell = GTK_CELL_RENDERER (object); if (!glade_gtk_cell_layout_has_renderer (layout, cell)) return FALSE; if ((gmodel = glade_cell_renderer_get_model (widget)) == NULL) return FALSE; glade_widget_property_get (gmodel, "columns", &column_list); columns = g_list_length (column_list); gtk_cell_layout_clear_attributes (layout, cell); for (l = glade_widget_get_properties (widget); l; l = l->next) { property = l->data; pdef = glade_property_get_def (property); if (strncmp (glade_property_def_id (pdef), "attr-", attr_len) == 0) { gint column = g_value_get_int (glade_property_inline_value (property)); attr_prop_name = (gchar *)&glade_property_def_id (pdef)[attr_len]; if (column >= 0 && column < columns) { GladeColumnType *column_type = (GladeColumnType *) g_list_nth_data (column_list, column); GType column_gtype = g_type_from_name (column_type->type_name); GParamSpec *pspec = glade_property_def_get_pspec (pdef); if (column_gtype && g_value_type_transformable (column_gtype, pspec->value_type)) gtk_cell_layout_add_attribute (layout, cell, attr_prop_name, column); } } } return FALSE; }