Blame plugins/gtk+/glade-gtk-cell-renderer.c

Packit 1e8aac
/*
Packit 1e8aac
 * glade-gtk-cell-renderer.c - GladeWidgetAdaptor for GtkCellRenderer
Packit 1e8aac
 *
Packit 1e8aac
 * Copyright (C) 2013 Tristan Van Berkom
Packit 1e8aac
 *
Packit 1e8aac
 * Authors:
Packit 1e8aac
 *      Tristan Van Berkom <tristan.van.berkom@gmail.com>
Packit 1e8aac
 *
Packit 1e8aac
 * This library is free software; you can redistribute it and/or modify it
Packit 1e8aac
 * under the terms of the GNU Lesser General Public License as
Packit 1e8aac
 * published by the Free Software Foundation; either version 2.1 of
Packit 1e8aac
 * the License, or (at your option) any later version.
Packit 1e8aac
 *
Packit 1e8aac
 * This library is distributed in the hope that it will be useful, but
Packit 1e8aac
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1e8aac
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1e8aac
 * Lesser General Public License for more details.
Packit 1e8aac
 *
Packit 1e8aac
 * You should have received a copy of the GNU Lesser General Public 
Packit 1e8aac
 * License along with this program; if not, write to the Free Software
Packit 1e8aac
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include <config.h>
Packit 1e8aac
#include <glib/gi18n-lib.h>
Packit 1e8aac
#include <gladeui/glade.h>
Packit 1e8aac
Packit 1e8aac
#include "glade-gtk-image.h" /* For GtkIconSize serialization */
Packit 1e8aac
#include "glade-gtk-tree-view.h"
Packit 1e8aac
#include "glade-gtk-cell-renderer.h"
Packit 1e8aac
#include "glade-cell-renderer-editor.h"
Packit 1e8aac
#include "glade-column-types.h"
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_cell_renderer_action_activate (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                         GObject * object,
Packit 1e8aac
                                         const gchar * action_path)
Packit 1e8aac
{
Packit 1e8aac
  if (strcmp (action_path, "launch_editor") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      GladeWidget *w = glade_widget_get_from_gobject (object);
Packit 1e8aac
Packit 1e8aac
      while ((w = glade_widget_get_parent (w)))
Packit 1e8aac
        {
Packit 1e8aac
	  GObject *object = glade_widget_get_object (w);
Packit 1e8aac
Packit 1e8aac
          if (GTK_IS_TREE_VIEW (object))
Packit 1e8aac
            {
Packit 1e8aac
              glade_gtk_treeview_launch_editor (object);
Packit 1e8aac
              break;
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor, object, action_path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_cell_renderer_deep_post_create (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                          GObject * object,
Packit 1e8aac
                                          GladeCreateReason reason)
Packit 1e8aac
{
Packit 1e8aac
  GladePropertyClass *pclass;
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  GladeWidget *widget;
Packit 1e8aac
  const GList *l;
Packit 1e8aac
Packit 1e8aac
  widget = glade_widget_get_from_gobject (object);
Packit 1e8aac
Packit 1e8aac
  for (l = glade_widget_adaptor_get_properties (adaptor); l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      pclass = l->data;
Packit 1e8aac
Packit 1e8aac
      if (strncmp (glade_property_class_id (pclass), "use-attr-", strlen ("use-attr-")) == 0)
Packit 1e8aac
        {
Packit 1e8aac
          property = glade_widget_get_property (widget, glade_property_class_id (pclass));
Packit 1e8aac
          glade_property_sync (property);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes, object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeEditorProperty *
Packit 1e8aac
glade_gtk_cell_renderer_create_eprop (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                      GladePropertyClass * klass,
Packit 1e8aac
                                      gboolean use_command)
Packit 1e8aac
{
Packit 1e8aac
  GladeEditorProperty *eprop;
Packit 1e8aac
Packit 1e8aac
  if (strncmp (glade_property_class_id (klass), "attr-", strlen ("attr-")) == 0)
Packit 1e8aac
    eprop = g_object_new (GLADE_TYPE_EPROP_CELL_ATTRIBUTE,
Packit 1e8aac
                          "property-class", klass,
Packit 1e8aac
                          "use-command", use_command, NULL);
Packit 1e8aac
  else
Packit 1e8aac
    eprop = GWA_GET_CLASS
Packit 1e8aac
        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
Packit 1e8aac
  return eprop;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
GladeEditable *
Packit 1e8aac
glade_gtk_cell_renderer_create_editable (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                         GladeEditorPageType type)
Packit 1e8aac
{
Packit 1e8aac
  GladeEditable *editable;
Packit 1e8aac
Packit 1e8aac
  /* Get base editable */
Packit 1e8aac
  editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
Packit 1e8aac
Packit 1e8aac
  if (type == GLADE_PAGE_GENERAL || type == GLADE_PAGE_COMMON)
Packit 1e8aac
    return (GladeEditable *) glade_cell_renderer_editor_new (adaptor, type,
Packit 1e8aac
                                                             editable);
Packit 1e8aac
Packit 1e8aac
  return editable;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_cell_renderer_set_use_attribute (GObject * object,
Packit 1e8aac
                                           const gchar * property_name,
Packit 1e8aac
                                           const GValue * value)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *widget = glade_widget_get_from_gobject (object);
Packit 1e8aac
  gchar *attr_prop_name, *prop_msg, *attr_msg;
Packit 1e8aac
Packit 1e8aac
  attr_prop_name = g_strdup_printf ("attr-%s", property_name);
Packit 1e8aac
Packit 1e8aac
  prop_msg = g_strdup_printf (_("%s is set to load %s from the model"),
Packit 1e8aac
                              glade_widget_get_name (widget), property_name);
Packit 1e8aac
  attr_msg = g_strdup_printf (_("%s is set to manipulate %s directly"),
Packit 1e8aac
                              glade_widget_get_name (widget), attr_prop_name);
Packit 1e8aac
Packit 1e8aac
  glade_widget_property_set_sensitive (widget, property_name, FALSE, prop_msg);
Packit 1e8aac
  glade_widget_property_set_sensitive (widget, attr_prop_name, FALSE, attr_msg);
Packit 1e8aac
Packit 1e8aac
  if (g_value_get_boolean (value))
Packit 1e8aac
    glade_widget_property_set_sensitive (widget, attr_prop_name, TRUE, NULL);
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      GladeProperty *property =
Packit 1e8aac
          glade_widget_get_property (widget, property_name);
Packit 1e8aac
Packit 1e8aac
      glade_property_set_sensitive (property, TRUE, NULL);
Packit 1e8aac
      glade_property_sync (property);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (prop_msg);
Packit 1e8aac
  g_free (attr_msg);
Packit 1e8aac
  g_free (attr_prop_name);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static GladeProperty *
Packit 1e8aac
glade_gtk_cell_renderer_attribute_switch (GladeWidget * gwidget,
Packit 1e8aac
                                          const gchar * property_name)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  gchar *use_attr_name = g_strdup_printf ("use-attr-%s", property_name);
Packit 1e8aac
Packit 1e8aac
  property = glade_widget_get_property (gwidget, use_attr_name);
Packit 1e8aac
  g_free (use_attr_name);
Packit 1e8aac
Packit 1e8aac
  return property;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
glade_gtk_cell_renderer_property_enabled (GObject * object,
Packit 1e8aac
                                          const gchar * property_name)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
Packit 1e8aac
  gboolean use_attr = TRUE;
Packit 1e8aac
Packit 1e8aac
  if ((property =
Packit 1e8aac
       glade_gtk_cell_renderer_attribute_switch (gwidget,
Packit 1e8aac
                                                 property_name)) != NULL)
Packit 1e8aac
    glade_property_get (property, &use_attr);
Packit 1e8aac
Packit 1e8aac
  return !use_attr;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_cell_renderer_set_property (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                      GObject * object,
Packit 1e8aac
                                      const gchar * property_name,
Packit 1e8aac
                                      const GValue * value)
Packit 1e8aac
{
Packit 1e8aac
  static gint use_attr_len = 0;
Packit 1e8aac
  static gint attr_len = 0;
Packit 1e8aac
Packit 1e8aac
  if (!attr_len)
Packit 1e8aac
    {
Packit 1e8aac
      use_attr_len = strlen ("use-attr-");
Packit 1e8aac
      attr_len = strlen ("attr-");
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (strncmp (property_name, "use-attr-", use_attr_len) == 0)
Packit 1e8aac
    glade_gtk_cell_renderer_set_use_attribute (object,
Packit 1e8aac
                                               &property_name[use_attr_len],
Packit 1e8aac
                                               value);
Packit 1e8aac
  else if (strncmp (property_name, "attr-", attr_len) == 0)
Packit 1e8aac
    glade_gtk_cell_renderer_sync_attributes (object);
Packit 1e8aac
  else if (glade_gtk_cell_renderer_property_enabled (object, property_name))
Packit 1e8aac
    /* Chain Up */
Packit 1e8aac
    GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
Packit 1e8aac
                                                 object, property_name, value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_cell_renderer_write_properties (GladeWidget * widget,
Packit 1e8aac
                                          GladeXmlContext * context,
Packit 1e8aac
                                          GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property, *prop;
Packit 1e8aac
  GladePropertyClass *pclass;
Packit 1e8aac
  gchar *attr_name;
Packit 1e8aac
  GList *l;
Packit 1e8aac
  static gint attr_len = 0;
Packit 1e8aac
Packit 1e8aac
  if (!attr_len)
Packit 1e8aac
    attr_len = strlen ("attr-");
Packit 1e8aac
Packit 1e8aac
  for (l = glade_widget_get_properties (widget); l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      property = l->data;
Packit 1e8aac
      pclass   = glade_property_get_class (property);
Packit 1e8aac
Packit 1e8aac
      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
Packit 1e8aac
        {
Packit 1e8aac
          gchar *use_attr_str;
Packit 1e8aac
          gboolean use_attr = FALSE;
Packit 1e8aac
Packit 1e8aac
          use_attr_str = g_strdup_printf ("use-%s", glade_property_class_id (pclass));
Packit 1e8aac
          glade_widget_property_get (widget, use_attr_str, &use_attr);
Packit 1e8aac
Packit 1e8aac
          attr_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
Packit 1e8aac
          prop = glade_widget_get_property (widget, attr_name);
Packit 1e8aac
Packit 1e8aac
          if (!use_attr && prop)
Packit 1e8aac
	    {
Packit 1e8aac
	      /* Special case to write GtkCellRendererPixbuf:stock-size */
Packit 1e8aac
	      if (strcmp (attr_name, "stock-size") == 0)
Packit 1e8aac
		glade_gtk_write_icon_size (widget, context, node, "stock-size");
Packit 1e8aac
	      else
Packit 1e8aac
		glade_property_write (prop, context, node);
Packit 1e8aac
	    }
Packit 1e8aac
Packit 1e8aac
          g_free (use_attr_str);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_cell_renderer_write_widget (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                      GladeWidget * widget,
Packit 1e8aac
                                      GladeXmlContext * context,
Packit 1e8aac
                                      GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
Packit 1e8aac
	glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* Write our normal properties, then chain up to write any other normal properties,
Packit 1e8aac
   * then attributes 
Packit 1e8aac
   */
Packit 1e8aac
  glade_gtk_cell_renderer_write_properties (widget, context, node);
Packit 1e8aac
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_cell_renderer_parse_finished (GladeProject * project,
Packit 1e8aac
                                        GladeWidget * widget)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  GList *l;
Packit 1e8aac
  static gint attr_len = 0, use_attr_len = 0;
Packit 1e8aac
Packit 1e8aac
  /* Set "use-attr-*" everywhere that the object property is non-default 
Packit 1e8aac
   *
Packit 1e8aac
   * We do this in the finished handler because some properties may be
Packit 1e8aac
   * object type properties (which may be anywhere in the glade file).
Packit 1e8aac
   */
Packit 1e8aac
  if (!attr_len)
Packit 1e8aac
    {
Packit 1e8aac
      attr_len = strlen ("attr-");
Packit 1e8aac
      use_attr_len = strlen ("use-attr-");
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  for (l = glade_widget_get_properties (widget); l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProperty *switch_prop;
Packit 1e8aac
      GladePropertyClass *pclass;
Packit 1e8aac
Packit 1e8aac
      property = l->data;
Packit 1e8aac
      pclass   = glade_property_get_class (property);
Packit 1e8aac
Packit 1e8aac
      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) != 0 &&
Packit 1e8aac
          strncmp (glade_property_class_id (pclass), "use-attr-", use_attr_len) != 0 &&
Packit 1e8aac
          (switch_prop =
Packit 1e8aac
           glade_gtk_cell_renderer_attribute_switch (widget,
Packit 1e8aac
                                                     glade_property_class_id (pclass))) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          if (glade_property_original_default (property))
Packit 1e8aac
            glade_property_set (switch_prop, TRUE);
Packit 1e8aac
          else
Packit 1e8aac
            glade_property_set (switch_prop, FALSE);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_cell_renderer_read_widget (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                     GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
Packit 1e8aac
	glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* First chain up and read in all the properties... */
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (glade_widget_get_project (widget), "parse-finished",
Packit 1e8aac
                    G_CALLBACK (glade_gtk_cell_renderer_parse_finished),
Packit 1e8aac
                    widget);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
glade_gtk_cell_layout_has_renderer (GtkCellLayout * layout,
Packit 1e8aac
                                    GtkCellRenderer * renderer)
Packit 1e8aac
{
Packit 1e8aac
  GList *cells = gtk_cell_layout_get_cells (layout);
Packit 1e8aac
  gboolean has_renderer;
Packit 1e8aac
Packit 1e8aac
  has_renderer = (g_list_find (cells, renderer) != NULL);
Packit 1e8aac
Packit 1e8aac
  g_list_free (cells);
Packit 1e8aac
Packit 1e8aac
  return has_renderer;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gboolean
Packit 1e8aac
glade_gtk_cell_renderer_sync_attributes (GObject * object)
Packit 1e8aac
{
Packit 1e8aac
Packit 1e8aac
  GtkCellLayout *layout;
Packit 1e8aac
  GtkCellRenderer *cell;
Packit 1e8aac
  GladeWidget *widget;
Packit 1e8aac
  GladeWidget *parent;
Packit 1e8aac
  GladeWidget *gmodel;
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  GladePropertyClass *pclass;
Packit 1e8aac
  gchar *attr_prop_name;
Packit 1e8aac
  GList *l, *column_list = NULL;
Packit 1e8aac
  gint columns = 0;
Packit 1e8aac
  static gint attr_len = 0;
Packit 1e8aac
Packit 1e8aac
  if (!attr_len)
Packit 1e8aac
    attr_len = strlen ("attr-");
Packit 1e8aac
Packit 1e8aac
  /* Apply attributes to renderer when bound to a model in runtime */
Packit 1e8aac
  widget = glade_widget_get_from_gobject (object);
Packit 1e8aac
Packit 1e8aac
  parent = glade_widget_get_parent (widget);
Packit 1e8aac
  if (parent == NULL)
Packit 1e8aac
    return FALSE;
Packit 1e8aac
Packit 1e8aac
  /* When creating widgets, sometimes the parent is set before parenting happens,
Packit 1e8aac
   * here we have to be careful for that..
Packit 1e8aac
   */
Packit 1e8aac
  layout = GTK_CELL_LAYOUT (glade_widget_get_object (parent));
Packit 1e8aac
  cell   = GTK_CELL_RENDERER (object);
Packit 1e8aac
Packit 1e8aac
  if (!glade_gtk_cell_layout_has_renderer (layout, cell))
Packit 1e8aac
    return FALSE;
Packit 1e8aac
Packit 1e8aac
  if ((gmodel = glade_cell_renderer_get_model (widget)) == NULL)
Packit 1e8aac
    return FALSE;
Packit 1e8aac
Packit 1e8aac
  glade_widget_property_get (gmodel, "columns", &column_list);
Packit 1e8aac
  columns = g_list_length (column_list);
Packit 1e8aac
Packit 1e8aac
  gtk_cell_layout_clear_attributes (layout, cell);
Packit 1e8aac
Packit 1e8aac
  for (l = glade_widget_get_properties (widget); l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      property = l->data;
Packit 1e8aac
      pclass   = glade_property_get_class (property);
Packit 1e8aac
Packit 1e8aac
      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
Packit 1e8aac
        {
Packit 1e8aac
          gint column = g_value_get_int (glade_property_inline_value (property));
Packit 1e8aac
Packit 1e8aac
          attr_prop_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
Packit 1e8aac
Packit 1e8aac
          if (column >= 0 && column < columns)
Packit 1e8aac
            {
Packit 1e8aac
              GladeColumnType *column_type =
Packit 1e8aac
                  (GladeColumnType *) g_list_nth_data (column_list, column);
Packit 1e8aac
              GType column_gtype = g_type_from_name (column_type->type_name);
Packit 1e8aac
	      GParamSpec *pspec = glade_property_class_get_pspec (pclass);
Packit 1e8aac
Packit 1e8aac
              if (column_gtype &&
Packit 1e8aac
                  g_value_type_transformable (column_gtype, pspec->value_type))
Packit 1e8aac
                gtk_cell_layout_add_attribute (layout, cell, attr_prop_name, column);
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}