Blame plugins/gtk+/glade-gtk-widget.c

Packit 1e8aac
/*
Packit 1e8aac
 * glade-gtk-widget.c - GladeWidgetAdaptor for GtkWidget
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
#include <config.h>
Packit 1e8aac
#include <glib/gi18n-lib.h>
Packit 1e8aac
#include <gladeui/glade.h>
Packit 1e8aac
#include <string.h>
Packit 1e8aac
Packit 1e8aac
#include "glade-widget-editor.h"
Packit 1e8aac
#include "glade-string-list.h"
Packit 1e8aac
#include "glade-accels.h"
Packit 1e8aac
Packit 1e8aac
#define GLADE_TAG_A11Y_A11Y         "accessibility"
Packit 1e8aac
#define GLADE_TAG_A11Y_ACTION_NAME  "action_name"       /* We should make -/_ synonymous */
Packit 1e8aac
#define GLADE_TAG_A11Y_DESC         "description"
Packit 1e8aac
#define GLADE_TAG_A11Y_TARGET       "target"
Packit 1e8aac
#define GLADE_TAG_A11Y_TYPE         "type"
Packit 1e8aac
Packit 1e8aac
#define GLADE_TAG_A11Y_INTERNAL_NAME "accessible"
Packit 1e8aac
Packit 1e8aac
#define GLADE_TAG_A11Y_RELATION     "relation"
Packit 1e8aac
#define GLADE_TAG_A11Y_ACTION       "action"
Packit 1e8aac
#define GLADE_TAG_A11Y_PROPERTY     "property"
Packit 1e8aac
Packit 1e8aac
#define GLADE_TAG_STYLE             "style"
Packit 1e8aac
#define GLADE_TAG_CLASS             "class"
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
/* This function does absolutely nothing
Packit 1e8aac
 * (and is for use in overriding some post_create functions
Packit 1e8aac
 * throughout the catalog).
Packit 1e8aac
 */
Packit 1e8aac
void
Packit 1e8aac
empty (GObject * container, GladeCreateReason reason)
Packit 1e8aac
{
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static const gchar *atk_relations_list[] = {
Packit 1e8aac
  "controlled-by",
Packit 1e8aac
  "controller-for",
Packit 1e8aac
  "labelled-by",
Packit 1e8aac
  "label-for",
Packit 1e8aac
  "member-of",
Packit 1e8aac
  "node-child-of",
Packit 1e8aac
  "flows-to",
Packit 1e8aac
  "flows-from",
Packit 1e8aac
  "subwindow-of",
Packit 1e8aac
  "embeds",
Packit 1e8aac
  "embedded-by",
Packit 1e8aac
  "popup-for",
Packit 1e8aac
  "parent-window-of",
Packit 1e8aac
  "described-by",
Packit 1e8aac
  "description-for",
Packit 1e8aac
  NULL
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_destroy_object (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
				 GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  gtk_widget_destroy (GTK_WIDGET (object));
Packit 1e8aac
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->destroy_object (adaptor, object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_parse_atk_relation (GladeProperty * property, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *prop;
Packit 1e8aac
  GladePropertyClass *pclass;
Packit 1e8aac
  gchar *type, *target, *id, *tmp;
Packit 1e8aac
  gchar *string = NULL;
Packit 1e8aac
Packit 1e8aac
  for (prop = glade_xml_node_get_children (node);
Packit 1e8aac
       prop; prop = glade_xml_node_next (prop))
Packit 1e8aac
    {
Packit 1e8aac
      if (!glade_xml_node_verify_silent (prop, GLADE_TAG_A11Y_RELATION))
Packit 1e8aac
        continue;
Packit 1e8aac
Packit 1e8aac
      if (!(type =
Packit 1e8aac
            glade_xml_get_property_string_required
Packit 1e8aac
            (prop, GLADE_TAG_A11Y_TYPE, NULL)))
Packit 1e8aac
        continue;
Packit 1e8aac
Packit 1e8aac
      if (!(target =
Packit 1e8aac
            glade_xml_get_property_string_required
Packit 1e8aac
            (prop, GLADE_TAG_A11Y_TARGET, NULL)))
Packit 1e8aac
        {
Packit 1e8aac
          g_free (type);
Packit 1e8aac
          continue;
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      id     = glade_util_read_prop_name (type);
Packit 1e8aac
      pclass = glade_property_get_class (property);
Packit 1e8aac
Packit 1e8aac
      if (!strcmp (id, glade_property_class_id (pclass)))
Packit 1e8aac
        {
Packit 1e8aac
          if (string == NULL)
Packit 1e8aac
            string = g_strdup (target);
Packit 1e8aac
          else
Packit 1e8aac
            {
Packit 1e8aac
              tmp = g_strdup_printf ("%s%s%s", string,
Packit 1e8aac
                                     GPC_OBJECT_DELIMITER, target);
Packit 1e8aac
              string = (g_free (string), tmp);
Packit 1e8aac
            }
Packit 1e8aac
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      g_free (id);
Packit 1e8aac
      g_free (type);
Packit 1e8aac
      g_free (target);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* we must synchronize this directly after loading this project
Packit 1e8aac
   * (i.e. lookup the actual objects after they've been parsed and
Packit 1e8aac
   * are present). this is a feature of object and object list properties
Packit 1e8aac
   * that needs a better api.
Packit 1e8aac
   */
Packit 1e8aac
  if (string)
Packit 1e8aac
    {
Packit 1e8aac
      g_object_set_data_full (G_OBJECT (property), "glade-loaded-object",
Packit 1e8aac
			      /* 'string' here is already allocated on the heap */
Packit 1e8aac
                              string, g_free);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_parse_atk_props (GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *prop;
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  GValue *gvalue;
Packit 1e8aac
  gchar *value, *name, *id, *comment;
Packit 1e8aac
  gint translatable;
Packit 1e8aac
  gboolean is_action;
Packit 1e8aac
Packit 1e8aac
  for (prop = glade_xml_node_get_children (node);
Packit 1e8aac
       prop; prop = glade_xml_node_next (prop))
Packit 1e8aac
    {
Packit 1e8aac
      if (glade_xml_node_verify_silent (prop, GLADE_TAG_A11Y_PROPERTY))
Packit 1e8aac
        is_action = FALSE;
Packit 1e8aac
      else if (glade_xml_node_verify_silent (prop, GLADE_TAG_A11Y_ACTION))
Packit 1e8aac
        is_action = TRUE;
Packit 1e8aac
      else
Packit 1e8aac
        continue;
Packit 1e8aac
Packit 1e8aac
      if (!is_action &&
Packit 1e8aac
          !(name = glade_xml_get_property_string_required
Packit 1e8aac
            (prop, GLADE_XML_TAG_NAME, NULL)))
Packit 1e8aac
        continue;
Packit 1e8aac
      else if (is_action &&
Packit 1e8aac
               !(name = glade_xml_get_property_string_required
Packit 1e8aac
                 (prop, GLADE_TAG_A11Y_ACTION_NAME, NULL)))
Packit 1e8aac
        continue;
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
      /* Make sure we are working with dashes and
Packit 1e8aac
       * not underscores ... 
Packit 1e8aac
       */
Packit 1e8aac
      id = glade_util_read_prop_name (name);
Packit 1e8aac
      g_free (name);
Packit 1e8aac
Packit 1e8aac
      /* We are namespacing the action properties internally
Packit 1e8aac
       * just incase they clash (all property names must be
Packit 1e8aac
       * unique...)
Packit 1e8aac
       */
Packit 1e8aac
      if (is_action)
Packit 1e8aac
        {
Packit 1e8aac
          name = g_strdup_printf ("atk-%s", id);
Packit 1e8aac
          g_free (id);
Packit 1e8aac
          id = name;
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      if ((property = glade_widget_get_property (widget, id)) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          /* Complex statement just getting the value here... */
Packit 1e8aac
          if ((!is_action &&
Packit 1e8aac
               !(value = glade_xml_get_content (prop))) ||
Packit 1e8aac
              (is_action &&
Packit 1e8aac
               !(value = glade_xml_get_property_string_required
Packit 1e8aac
                 (prop, GLADE_TAG_A11Y_DESC, NULL))))
Packit 1e8aac
            {
Packit 1e8aac
              /* XXX should be a glade_xml_get_content_required()... */
Packit 1e8aac
              g_free (id);
Packit 1e8aac
              continue;
Packit 1e8aac
            }
Packit 1e8aac
Packit 1e8aac
          /* Set the parsed value on the property ... */
Packit 1e8aac
          gvalue = glade_property_class_make_gvalue_from_string
Packit 1e8aac
	    (glade_property_get_class (property), value, glade_widget_get_project (widget));
Packit 1e8aac
          glade_property_set_value (property, gvalue);
Packit 1e8aac
          g_value_unset (gvalue);
Packit 1e8aac
          g_free (gvalue);
Packit 1e8aac
Packit 1e8aac
          /* Deal with i18n... ... XXX Do i18n context !!! */
Packit 1e8aac
          translatable = glade_xml_get_property_boolean
Packit 1e8aac
              (prop, GLADE_TAG_TRANSLATABLE, FALSE);
Packit 1e8aac
          comment = glade_xml_get_property_string (prop, GLADE_TAG_COMMENT);
Packit 1e8aac
Packit 1e8aac
          glade_property_i18n_set_translatable (property, translatable);
Packit 1e8aac
          glade_property_i18n_set_comment (property, comment);
Packit 1e8aac
Packit 1e8aac
          g_free (comment);
Packit 1e8aac
          g_free (value);
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      g_free (id);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_parse_atk_props_gtkbuilder (GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *child, *object_node;
Packit 1e8aac
  gchar *internal;
Packit 1e8aac
Packit 1e8aac
  /* Search for internal "accessible" child and redirect parse from there */
Packit 1e8aac
  for (child = glade_xml_node_get_children (node);
Packit 1e8aac
       child; child = glade_xml_node_next (child))
Packit 1e8aac
    {
Packit 1e8aac
      if (glade_xml_node_verify_silent (child, GLADE_XML_TAG_CHILD))
Packit 1e8aac
        {
Packit 1e8aac
          if ((internal =
Packit 1e8aac
               glade_xml_get_property_string (child,
Packit 1e8aac
                                              GLADE_XML_TAG_INTERNAL_CHILD)))
Packit 1e8aac
            {
Packit 1e8aac
              if (!strcmp (internal, GLADE_TAG_A11Y_INTERNAL_NAME) &&
Packit 1e8aac
                  (object_node =
Packit 1e8aac
                   glade_xml_search_child_required (child,
Packit 1e8aac
                                                    GLADE_XML_TAG_WIDGET)))
Packit 1e8aac
                glade_gtk_parse_atk_props (widget, object_node);
Packit 1e8aac
Packit 1e8aac
              g_free (internal);
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_read_atk_props (GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *atk_node;
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  gint i;
Packit 1e8aac
Packit 1e8aac
  glade_gtk_parse_atk_props_gtkbuilder (widget, node);
Packit 1e8aac
Packit 1e8aac
  if ((atk_node = glade_xml_search_child (node, GLADE_TAG_A11Y_A11Y)) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      /* Properties & actions */
Packit 1e8aac
      glade_gtk_parse_atk_props (widget, atk_node);
Packit 1e8aac
Packit 1e8aac
      /* Relations */
Packit 1e8aac
      for (i = 0; atk_relations_list[i]; i++)
Packit 1e8aac
        {
Packit 1e8aac
          if ((property =
Packit 1e8aac
               glade_widget_get_property (widget, atk_relations_list[i])))
Packit 1e8aac
            glade_gtk_parse_atk_relation (property, atk_node);
Packit 1e8aac
          else
Packit 1e8aac
            g_warning ("Couldnt find atk relation %s", atk_relations_list[i]);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_read_style_classes (GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *style_node;
Packit 1e8aac
  GladeXmlNode *class_node;
Packit 1e8aac
  GList        *string_list = NULL;
Packit 1e8aac
Packit 1e8aac
  if ((style_node = glade_xml_search_child (node, GLADE_TAG_STYLE)) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      for (class_node = glade_xml_node_get_children (style_node);
Packit 1e8aac
	   class_node; class_node = glade_xml_node_next (class_node))
Packit 1e8aac
	{
Packit 1e8aac
	  gchar *name;
Packit 1e8aac
Packit 1e8aac
	  if (!glade_xml_node_verify (class_node, GLADE_TAG_CLASS))
Packit 1e8aac
	    continue;
Packit 1e8aac
Packit 1e8aac
	  name = glade_xml_get_property_string (class_node, GLADE_TAG_NAME);
Packit 1e8aac
Packit 1e8aac
	  string_list = glade_string_list_append (string_list, name, NULL, NULL, FALSE, NULL);
Packit 1e8aac
Packit 1e8aac
	  g_free (name);
Packit 1e8aac
	}
Packit 1e8aac
Packit 1e8aac
      glade_widget_property_set (widget, "glade-style-classes", string_list);
Packit 1e8aac
      glade_string_list_free (string_list);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_read_widget (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                              GladeWidget * widget, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  const gchar *tooltip_markup = NULL;
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 normal properties.. */
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
Packit 1e8aac
Packit 1e8aac
  /* Read in accelerators */
Packit 1e8aac
  glade_gtk_read_accels (widget, node, TRUE);
Packit 1e8aac
Packit 1e8aac
  /* Read in atk props */
Packit 1e8aac
  glade_gtk_widget_read_atk_props (widget, node);
Packit 1e8aac
Packit 1e8aac
  /* Read in the style classes */
Packit 1e8aac
  glade_gtk_widget_read_style_classes (widget, node);
Packit 1e8aac
Packit 1e8aac
  /* Resolve the virtual tooltip use markup property */
Packit 1e8aac
  glade_widget_property_get (widget, "tooltip-markup", &tooltip_markup);
Packit 1e8aac
  if (tooltip_markup != NULL)
Packit 1e8aac
    glade_widget_property_set (widget, "glade-tooltip-markup", TRUE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_property (GladeProperty * property,
Packit 1e8aac
                                     GladeXmlContext * context,
Packit 1e8aac
                                     GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  gchar *value = glade_property_make_string (property);
Packit 1e8aac
Packit 1e8aac
  if (value && value[0])
Packit 1e8aac
    {
Packit 1e8aac
      GladePropertyClass *pclass = glade_property_get_class (property);
Packit 1e8aac
      GladeXmlNode *prop_node = glade_xml_node_new (context, GLADE_TAG_A11Y_PROPERTY);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_append_child (node, prop_node);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                          GLADE_TAG_NAME, glade_property_class_id (pclass));
Packit 1e8aac
Packit 1e8aac
      glade_xml_set_content (prop_node, value);
Packit 1e8aac
Packit 1e8aac
      if (glade_property_i18n_get_translatable (property))
Packit 1e8aac
        glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                            GLADE_TAG_TRANSLATABLE,
Packit 1e8aac
                                            GLADE_XML_TAG_I18N_TRUE);
Packit 1e8aac
Packit 1e8aac
      if (glade_property_i18n_get_comment (property))
Packit 1e8aac
        glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                            GLADE_TAG_COMMENT,
Packit 1e8aac
                                            glade_property_i18n_get_comment (property));
Packit 1e8aac
Packit 1e8aac
      if (glade_property_i18n_get_context (property))
Packit 1e8aac
        glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                            GLADE_TAG_CONTEXT,
Packit 1e8aac
                                            glade_property_i18n_get_context (property));
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_properties (GladeWidget * widget,
Packit 1e8aac
                                       GladeXmlContext * context,
Packit 1e8aac
                                       GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *child_node, *object_node;
Packit 1e8aac
  GladeProperty *name_prop, *desc_prop, *role_prop;
Packit 1e8aac
Packit 1e8aac
  name_prop = glade_widget_get_property (widget, "AtkObject::accessible-name");
Packit 1e8aac
  desc_prop =
Packit 1e8aac
      glade_widget_get_property (widget, "AtkObject::accessible-description");
Packit 1e8aac
  role_prop = glade_widget_get_property (widget, "AtkObject::accessible-role");
Packit 1e8aac
Packit 1e8aac
  /* Create internal child here if any of these properties are non-null */
Packit 1e8aac
  if (!glade_property_default (name_prop) ||
Packit 1e8aac
      !glade_property_default (desc_prop) ||
Packit 1e8aac
      !glade_property_default (role_prop))
Packit 1e8aac
    {
Packit 1e8aac
      const gchar *widget_name = glade_widget_get_name (widget);
Packit 1e8aac
      gchar *atkname = NULL;
Packit 1e8aac
Packit 1e8aac
      if (!g_str_has_prefix (widget_name, GLADE_UNNAMED_PREFIX))
Packit 1e8aac
        atkname = g_strdup_printf ("%s-atkobject", widget_name);
Packit 1e8aac
Packit 1e8aac
      child_node = glade_xml_node_new (context, GLADE_XML_TAG_CHILD);
Packit 1e8aac
      glade_xml_node_append_child (node, child_node);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_set_property_string (child_node,
Packit 1e8aac
                                          GLADE_XML_TAG_INTERNAL_CHILD,
Packit 1e8aac
                                          GLADE_TAG_A11Y_INTERNAL_NAME);
Packit 1e8aac
Packit 1e8aac
      object_node = glade_xml_node_new (context, GLADE_XML_TAG_WIDGET);
Packit 1e8aac
      glade_xml_node_append_child (child_node, object_node);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_set_property_string (object_node,
Packit 1e8aac
                                          GLADE_XML_TAG_CLASS, "AtkObject");
Packit 1e8aac
Packit 1e8aac
      if (atkname)
Packit 1e8aac
        glade_xml_node_set_property_string (object_node,
Packit 1e8aac
                                            GLADE_XML_TAG_ID, atkname);
Packit 1e8aac
Packit 1e8aac
      if (!glade_property_default (name_prop))
Packit 1e8aac
        glade_gtk_widget_write_atk_property (name_prop, context, object_node);
Packit 1e8aac
      if (!glade_property_default (desc_prop))
Packit 1e8aac
        glade_gtk_widget_write_atk_property (desc_prop, context, object_node);
Packit 1e8aac
      if (!glade_property_default (role_prop))
Packit 1e8aac
        glade_gtk_widget_write_atk_property (role_prop, context, object_node);
Packit 1e8aac
Packit 1e8aac
      g_free (atkname);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_relation (GladeProperty * property,
Packit 1e8aac
                                     GladeXmlContext * context,
Packit 1e8aac
                                     GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *prop_node;
Packit 1e8aac
  GladePropertyClass *pclass;
Packit 1e8aac
  gchar *value, **split;
Packit 1e8aac
  gint i;
Packit 1e8aac
Packit 1e8aac
  if ((value = glade_widget_adaptor_string_from_value
Packit 1e8aac
       (glade_property_class_get_adaptor (glade_property_get_class (property)),
Packit 1e8aac
        glade_property_get_class (property), glade_property_inline_value (property))) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      if ((split = g_strsplit (value, GPC_OBJECT_DELIMITER, 0)) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          for (i = 0; split[i] != NULL; i++)
Packit 1e8aac
            {
Packit 1e8aac
	      pclass = glade_property_get_class (property);
Packit 1e8aac
Packit 1e8aac
              prop_node = glade_xml_node_new (context, GLADE_TAG_A11Y_RELATION);
Packit 1e8aac
              glade_xml_node_append_child (node, prop_node);
Packit 1e8aac
Packit 1e8aac
              glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                                  GLADE_TAG_A11Y_TYPE,
Packit 1e8aac
                                                  glade_property_class_id (pclass));
Packit 1e8aac
              glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                                  GLADE_TAG_A11Y_TARGET,
Packit 1e8aac
                                                  split[i]);
Packit 1e8aac
            }
Packit 1e8aac
          g_strfreev (split);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_relations (GladeWidget * widget,
Packit 1e8aac
                                      GladeXmlContext * context,
Packit 1e8aac
                                      GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  gint i;
Packit 1e8aac
Packit 1e8aac
  for (i = 0; atk_relations_list[i]; i++)
Packit 1e8aac
    {
Packit 1e8aac
      if ((property =
Packit 1e8aac
           glade_widget_get_property (widget, atk_relations_list[i])))
Packit 1e8aac
        glade_gtk_widget_write_atk_relation (property, context, node);
Packit 1e8aac
      else
Packit 1e8aac
        g_warning ("Couldnt find atk relation %s on widget %s",
Packit 1e8aac
                   atk_relations_list[i], glade_widget_get_name (widget));
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_action (GladeProperty * property,
Packit 1e8aac
                                   GladeXmlContext * context,
Packit 1e8aac
                                   GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  gchar *value = glade_property_make_string (property);
Packit 1e8aac
Packit 1e8aac
  if (value && value[0])
Packit 1e8aac
    {
Packit 1e8aac
      GladePropertyClass *pclass = glade_property_get_class (property);
Packit 1e8aac
      GladeXmlNode *prop_node = glade_xml_node_new (context, GLADE_TAG_A11Y_ACTION);
Packit 1e8aac
      glade_xml_node_append_child (node, prop_node);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                          GLADE_TAG_A11Y_ACTION_NAME,
Packit 1e8aac
                                          &glade_property_class_id (pclass)[4]);
Packit 1e8aac
      glade_xml_node_set_property_string (prop_node,
Packit 1e8aac
                                          GLADE_TAG_A11Y_DESC, value);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_actions (GladeWidget * widget,
Packit 1e8aac
                                    GladeXmlContext * context,
Packit 1e8aac
                                    GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
Packit 1e8aac
  if ((property = glade_widget_get_property (widget, "atk-click")) != NULL)
Packit 1e8aac
    glade_gtk_widget_write_atk_action (property, context, node);
Packit 1e8aac
  if ((property = glade_widget_get_property (widget, "atk-activate")) != NULL)
Packit 1e8aac
    glade_gtk_widget_write_atk_action (property, context, node);
Packit 1e8aac
  if ((property = glade_widget_get_property (widget, "atk-press")) != NULL)
Packit 1e8aac
    glade_gtk_widget_write_atk_action (property, context, node);
Packit 1e8aac
  if ((property = glade_widget_get_property (widget, "atk-release")) != NULL)
Packit 1e8aac
    glade_gtk_widget_write_atk_action (property, context, node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_atk_props (GladeWidget * widget,
Packit 1e8aac
                                  GladeXmlContext * context,
Packit 1e8aac
                                  GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *atk_node;
Packit 1e8aac
Packit 1e8aac
  atk_node = glade_xml_node_new (context, GLADE_TAG_A11Y_A11Y);
Packit 1e8aac
Packit 1e8aac
  glade_gtk_widget_write_atk_relations (widget, context, atk_node);
Packit 1e8aac
  glade_gtk_widget_write_atk_actions (widget, context, atk_node);
Packit 1e8aac
Packit 1e8aac
  if (!glade_xml_node_get_children (atk_node))
Packit 1e8aac
    glade_xml_node_delete (atk_node);
Packit 1e8aac
  else
Packit 1e8aac
    glade_xml_node_append_child (node, atk_node);
Packit 1e8aac
Packit 1e8aac
  glade_gtk_widget_write_atk_properties (widget, context, node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_write_style_classes (GladeWidget * widget,
Packit 1e8aac
				      GladeXmlContext * context,
Packit 1e8aac
				      GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeXmlNode *class_node, *style_node;
Packit 1e8aac
  GList        *string_list = NULL, *l;
Packit 1e8aac
  GladeString  *string;
Packit 1e8aac
Packit 1e8aac
  if (!glade_widget_property_get (widget, "glade-style-classes", &string_list) || !string_list)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  style_node = glade_xml_node_new (context, GLADE_TAG_STYLE);
Packit 1e8aac
Packit 1e8aac
  for (l = string_list; l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      string = l->data;
Packit 1e8aac
Packit 1e8aac
      class_node = glade_xml_node_new (context, GLADE_TAG_CLASS);
Packit 1e8aac
      glade_xml_node_append_child (style_node, class_node);
Packit 1e8aac
Packit 1e8aac
      glade_xml_node_set_property_string (class_node,
Packit 1e8aac
					  GLADE_TAG_NAME,
Packit 1e8aac
					  string->string);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (!glade_xml_node_get_children (style_node))
Packit 1e8aac
    glade_xml_node_delete (style_node);
Packit 1e8aac
  else
Packit 1e8aac
    glade_xml_node_append_child (node, style_node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_write_widget (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                               GladeWidget * widget,
Packit 1e8aac
                               GladeXmlContext * context, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  GladeProperty *prop;
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
  /* Make sure use-action-appearance and related-action properties are
Packit 1e8aac
   * ordered in a sane way and are only saved if there is an action */
Packit 1e8aac
  prop = glade_widget_get_property (widget, "use-action-appearance");
Packit 1e8aac
  if (prop && glade_property_get_enabled (prop))
Packit 1e8aac
    glade_property_write (prop, context, node);
Packit 1e8aac
Packit 1e8aac
  prop = glade_widget_get_property (widget, "related-action");
Packit 1e8aac
  if (prop && glade_property_get_enabled (prop))
Packit 1e8aac
    glade_property_write (prop, context, node);
Packit 1e8aac
Packit 1e8aac
  /* Finally chain up and read in all the normal properties.. */
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_write_widget_after (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
				     GladeWidget * widget,
Packit 1e8aac
				     GladeXmlContext * context, GladeXmlNode * node)
Packit 1e8aac
{
Packit 1e8aac
  /* The ATK properties are actually children */
Packit 1e8aac
  glade_gtk_widget_write_atk_props (widget, context, node);
Packit 1e8aac
Packit 1e8aac
  /* Put the accelerators and style classes after children */
Packit 1e8aac
  glade_gtk_write_accels (widget, context, node, TRUE);
Packit 1e8aac
  glade_gtk_widget_write_style_classes (widget, context, node);
Packit 1e8aac
Packit 1e8aac
  /* Finally chain up and read in all the normal properties.. */
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget_after (adaptor, widget, context, node);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeEditorProperty *
Packit 1e8aac
glade_gtk_widget_create_eprop (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                               GladePropertyClass * klass, gboolean use_command)
Packit 1e8aac
{
Packit 1e8aac
  GladeEditorProperty *eprop;
Packit 1e8aac
  GParamSpec          *pspec;
Packit 1e8aac
Packit 1e8aac
  pspec = glade_property_class_get_pspec (klass);
Packit 1e8aac
Packit 1e8aac
  /* chain up.. */
Packit 1e8aac
  if (pspec->value_type == GLADE_TYPE_ACCEL_GLIST)
Packit 1e8aac
    eprop = g_object_new (GLADE_TYPE_EPROP_ACCEL,
Packit 1e8aac
                          "property-class", klass,
Packit 1e8aac
                          "use-command", use_command, NULL);
Packit 1e8aac
  else if (pspec->value_type == GLADE_TYPE_STRING_LIST)
Packit 1e8aac
    eprop = glade_eprop_string_list_new (klass, use_command, FALSE, FALSE);
Packit 1e8aac
  else
Packit 1e8aac
    eprop = GWA_GET_CLASS
Packit 1e8aac
        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
Packit 1e8aac
Packit 1e8aac
  return eprop;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeEditable *
Packit 1e8aac
glade_gtk_widget_create_editable (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
				  GladeEditorPageType type)
Packit 1e8aac
{
Packit 1e8aac
  GladeEditable *editable;
Packit 1e8aac
Packit 1e8aac
  /* Get base editable */
Packit 1e8aac
  if (type == GLADE_PAGE_COMMON)
Packit 1e8aac
    editable = (GladeEditable *)glade_widget_editor_new ();
Packit 1e8aac
  else
Packit 1e8aac
    editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
Packit 1e8aac
Packit 1e8aac
  return editable;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gchar *
Packit 1e8aac
glade_gtk_widget_string_from_value (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                    GladePropertyClass * klass,
Packit 1e8aac
                                    const GValue * value)
Packit 1e8aac
{
Packit 1e8aac
  GParamSpec          *pspec;
Packit 1e8aac
Packit 1e8aac
  pspec = glade_property_class_get_pspec (klass);
Packit 1e8aac
Packit 1e8aac
  if (pspec->value_type == GLADE_TYPE_ACCEL_GLIST)
Packit 1e8aac
    return glade_accels_make_string (g_value_get_boxed (value));
Packit 1e8aac
  else if (pspec->value_type == GLADE_TYPE_STRING_LIST)
Packit 1e8aac
    {
Packit 1e8aac
      GList *list = g_value_get_boxed (value);
Packit 1e8aac
Packit 1e8aac
      return glade_string_list_to_string (list);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    return GWA_GET_CLASS
Packit 1e8aac
        (G_TYPE_OBJECT)->string_from_value (adaptor, klass, value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
widget_parent_changed (GtkWidget * widget,
Packit 1e8aac
                       GParamSpec * pspec, GladeWidgetAdaptor * adaptor)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget = glade_widget_get_from_gobject (widget);
Packit 1e8aac
  GladeWidget *parent;
Packit 1e8aac
Packit 1e8aac
  /* this could get called for a stale instance of an object
Packit 1e8aac
   * being rebuilt for a contruct-only property. */
Packit 1e8aac
  if (!gwidget)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  parent = glade_widget_get_parent (gwidget);
Packit 1e8aac
Packit 1e8aac
  if (parent && !glade_widget_get_internal (parent))
Packit 1e8aac
    glade_widget_set_action_sensitive (gwidget, "remove_parent", TRUE);
Packit 1e8aac
  else
Packit 1e8aac
    glade_widget_set_action_sensitive (gwidget, "remove_parent", FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_deep_post_create (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                   GObject * widget, GladeCreateReason reason)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget = glade_widget_get_from_gobject (widget);
Packit 1e8aac
Packit 1e8aac
  /* Work around bug 472555 by resetting the default event mask,
Packit 1e8aac
   * this way only user edits will be saved to the glade file. */
Packit 1e8aac
  if (reason == GLADE_CREATE_USER)
Packit 1e8aac
    glade_widget_property_reset (gwidget, "events");
Packit 1e8aac
Packit 1e8aac
  glade_widget_set_action_sensitive (gwidget, "remove_parent", FALSE);
Packit 1e8aac
Packit 1e8aac
  if (GWA_IS_TOPLEVEL (adaptor) || glade_widget_get_internal (gwidget))
Packit 1e8aac
    glade_widget_set_action_sensitive (gwidget, "add_parent", FALSE);
Packit 1e8aac
Packit 1e8aac
  /* Watch parents/projects and set actions sensitive/insensitive */
Packit 1e8aac
  if (!glade_widget_get_internal (gwidget))
Packit 1e8aac
    g_signal_connect (G_OBJECT (widget), "notify::parent",
Packit 1e8aac
                      G_CALLBACK (widget_parent_changed), adaptor);
Packit 1e8aac
Packit 1e8aac
  if (!glade_widget_adaptor_get_book (adaptor) || !glade_util_have_devhelp ())
Packit 1e8aac
    glade_widget_set_action_visible (gwidget, "read_documentation", FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_set_property (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                               GObject * object,
Packit 1e8aac
                               const gchar * id, const GValue * value)
Packit 1e8aac
{
Packit 1e8aac
  /* FIXME: is this still needed with the new gtk+ tooltips? */
Packit 1e8aac
  if (!strcmp (id, "tooltip"))
Packit 1e8aac
    {
Packit 1e8aac
      id = "tooltip-text";
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Setting can-focus in the runtime has been known to cause crashes */
Packit 1e8aac
  if (!strcmp (id, "can-focus"))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  if (!strcmp (id, "glade-style-classes"))
Packit 1e8aac
    {
Packit 1e8aac
      GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (object));
Packit 1e8aac
      GList *l, *styles;
Packit 1e8aac
Packit 1e8aac
      /* NOTE: we can not use gtk_style_context_list_classes() because we only
Packit 1e8aac
       * want to remove the classes we added not the ones added by the widget
Packit 1e8aac
       */
Packit 1e8aac
      styles = g_object_get_data (object, "glade-style-classes");
Packit 1e8aac
      for (l = styles; l; l = g_list_next (l))
Packit 1e8aac
	{
Packit 1e8aac
	  GladeString *style = l->data;
Packit 1e8aac
          gtk_style_context_remove_class (context, style->string);
Packit 1e8aac
	}
Packit 1e8aac
Packit 1e8aac
      for (l = g_value_get_boxed (value); l; l = g_list_next (l))
Packit 1e8aac
	{
Packit 1e8aac
	  GladeString *style = l->data;
Packit 1e8aac
	  gtk_style_context_add_class (context, style->string);
Packit 1e8aac
	}
Packit 1e8aac
Packit 1e8aac
      /* Save the list here so we can use it later on to remove them from the style context */
Packit 1e8aac
      g_object_set_data_full (object, "glade-style-classes",
Packit 1e8aac
                              glade_string_list_copy (g_value_get_boxed (value)),
Packit 1e8aac
                              (GDestroyNotify) glade_string_list_free);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
      GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor, object, id, value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_get_property (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                               GObject * object,
Packit 1e8aac
                               const gchar * id, GValue * value)
Packit 1e8aac
{
Packit 1e8aac
  if (!strcmp (id, "tooltip"))
Packit 1e8aac
    {
Packit 1e8aac
      id = "tooltip-text";
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  GWA_GET_CLASS (G_TYPE_OBJECT)->get_property (adaptor, object, id, value);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static GList *
Packit 1e8aac
create_command_property_list (GladeWidget * gnew, GList * saved_props)
Packit 1e8aac
{
Packit 1e8aac
  GList *l, *command_properties = NULL;
Packit 1e8aac
Packit 1e8aac
  for (l = saved_props; l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProperty *property = l->data;
Packit 1e8aac
      GladePropertyClass *pclass = glade_property_get_class (property);
Packit 1e8aac
      GladeProperty *orig_prop =
Packit 1e8aac
	glade_widget_get_pack_property (gnew, glade_property_class_id (pclass));
Packit 1e8aac
      GCSetPropData *pdata = g_new0 (GCSetPropData, 1);
Packit 1e8aac
Packit 1e8aac
      pdata->property = orig_prop;
Packit 1e8aac
      pdata->old_value = g_new0 (GValue, 1);
Packit 1e8aac
      pdata->new_value = g_new0 (GValue, 1);
Packit 1e8aac
Packit 1e8aac
      glade_property_get_value (orig_prop, pdata->old_value);
Packit 1e8aac
      glade_property_get_value (property, pdata->new_value);
Packit 1e8aac
Packit 1e8aac
      command_properties = g_list_prepend (command_properties, pdata);
Packit 1e8aac
    }
Packit 1e8aac
  return g_list_reverse (command_properties);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_gtk_widget_action_activate (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                  GObject * object, const gchar * action_path)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget = glade_widget_get_from_gobject (object), *gparent;
Packit 1e8aac
  GList this_widget = { 0, }, that_widget = { 0,};
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  gparent = glade_widget_get_parent (gwidget);
Packit 1e8aac
  project = glade_widget_get_project (gwidget);
Packit 1e8aac
Packit 1e8aac
  if (strcmp (action_path, "preview") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      glade_project_preview (project,
Packit 1e8aac
                             glade_widget_get_from_gobject ((gpointer) object));
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (action_path, "edit_separate") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      GtkWidget *dialog = glade_editor_dialog_for_widget (gwidget);
Packit 1e8aac
      gtk_widget_show_all (dialog);
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (action_path, "remove_parent") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      GladeWidget *new_gparent;
Packit 1e8aac
      GladeProperty *property;
Packit 1e8aac
Packit 1e8aac
      g_return_if_fail (gparent);
Packit 1e8aac
Packit 1e8aac
      property = glade_widget_get_parentless_widget_ref (gparent);
Packit 1e8aac
      new_gparent = glade_widget_get_parent (gparent);
Packit 1e8aac
Packit 1e8aac
      glade_command_push_group (_("Removing parent of %s"), glade_widget_get_name (gwidget));
Packit 1e8aac
Packit 1e8aac
      /* Remove "this" widget, If the parent we're removing is a parentless 
Packit 1e8aac
       * widget reference, the reference will be implicitly broken by the 'cut' command */
Packit 1e8aac
      this_widget.data = gwidget;
Packit 1e8aac
      glade_command_delete (&this_widget);
Packit 1e8aac
Packit 1e8aac
      /* Delete the parent */
Packit 1e8aac
      that_widget.data = gparent;
Packit 1e8aac
      glade_command_delete (&that_widget);
Packit 1e8aac
Packit 1e8aac
      /* Add "this" widget to the new parent, if there is no new parent this will re-add
Packit 1e8aac
       * the widget to the project at the toplevel without a parent
Packit 1e8aac
       */
Packit 1e8aac
      glade_command_add (&this_widget, new_gparent, NULL, project, FALSE);
Packit 1e8aac
Packit 1e8aac
      /* If the parent had a parentless widget reference, undoably add the child
Packit 1e8aac
       * as the new parentless widget reference here */
Packit 1e8aac
      if (property)
Packit 1e8aac
	glade_command_set_property (property, glade_widget_get_object (gwidget));
Packit 1e8aac
Packit 1e8aac
      glade_command_pop_group ();
Packit 1e8aac
    }
Packit 1e8aac
  else if (strncmp (action_path, "add_parent/", 11) == 0)
Packit 1e8aac
    {
Packit 1e8aac
      const gchar *action = action_path + 11;
Packit 1e8aac
      GType new_type = 0;
Packit 1e8aac
Packit 1e8aac
      if (strcmp (action, "alignment") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_ALIGNMENT;
Packit 1e8aac
      else if (strcmp (action, "viewport") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_VIEWPORT;
Packit 1e8aac
      else if (strcmp (action, "eventbox") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_EVENT_BOX;
Packit 1e8aac
      else if (strcmp (action, "frame") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_FRAME;
Packit 1e8aac
      else if (strcmp (action, "aspect_frame") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_ASPECT_FRAME;
Packit 1e8aac
      else if (strcmp (action, "scrolled_window") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_SCROLLED_WINDOW;
Packit 1e8aac
      else if (strcmp (action, "expander") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_EXPANDER;
Packit 1e8aac
      else if (strcmp (action, "grid") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_GRID;
Packit 1e8aac
      else if (strcmp (action, "box") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_BOX;
Packit 1e8aac
      else if (strcmp (action, "paned") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_PANED;
Packit 1e8aac
      else if (strcmp (action, "stack") == 0)
Packit 1e8aac
        new_type = GTK_TYPE_STACK;
Packit 1e8aac
Packit 1e8aac
      if (new_type)
Packit 1e8aac
        {
Packit 1e8aac
          GladeWidgetAdaptor *adaptor =
Packit 1e8aac
            glade_widget_adaptor_get_by_type (new_type);
Packit 1e8aac
          GList *saved_props, *prop_cmds;
Packit 1e8aac
	  GladeWidget *gnew_parent;
Packit 1e8aac
          GladeProperty *property;
Packit 1e8aac
Packit 1e8aac
          glade_command_push_group (_("Adding parent %s for %s"),
Packit 1e8aac
                                    glade_widget_adaptor_get_title (adaptor), 
Packit 1e8aac
				    glade_widget_get_name (gwidget));
Packit 1e8aac
Packit 1e8aac
          /* Record packing properties */
Packit 1e8aac
          saved_props =
Packit 1e8aac
	    glade_widget_dup_properties (gwidget, glade_widget_get_packing_properties (gwidget),
Packit 1e8aac
					 FALSE, FALSE, FALSE);
Packit 1e8aac
Packit 1e8aac
	  property = glade_widget_get_parentless_widget_ref (gwidget);
Packit 1e8aac
Packit 1e8aac
	  /* Remove "this" widget, If the parent we're removing is a parentless 
Packit 1e8aac
	   * widget reference, the reference will be implicitly broken by the 'cut' command */
Packit 1e8aac
          this_widget.data = gwidget;
Packit 1e8aac
          glade_command_delete (&this_widget);
Packit 1e8aac
Packit 1e8aac
          /* Create new widget and put it where the placeholder was */
Packit 1e8aac
          if ((gnew_parent =
Packit 1e8aac
               glade_command_create (adaptor, gparent, NULL, project)) != NULL)
Packit 1e8aac
            {
Packit 1e8aac
	      /* Now we created the new parent, if gwidget had a parentless widget reference...
Packit 1e8aac
	       * set that reference to the new parent instead */
Packit 1e8aac
	      if (property)
Packit 1e8aac
		glade_command_set_property (property, glade_widget_get_object (gnew_parent));
Packit 1e8aac
Packit 1e8aac
              /* Remove the alignment that we added in the frame's post_create... */
Packit 1e8aac
              if (new_type == GTK_TYPE_FRAME)
Packit 1e8aac
                {
Packit 1e8aac
                  GObject *frame = glade_widget_get_object (gnew_parent);
Packit 1e8aac
                  GladeWidget *galign =
Packit 1e8aac
                      glade_widget_get_from_gobject (gtk_bin_get_child (GTK_BIN (frame)));
Packit 1e8aac
                  GList to_delete = { 0, };
Packit 1e8aac
Packit 1e8aac
                  to_delete.data = galign;
Packit 1e8aac
                  glade_command_delete (&to_delete);
Packit 1e8aac
                }
Packit 1e8aac
Packit 1e8aac
              /* Create heavy-duty glade-command properties stuff */
Packit 1e8aac
              prop_cmds =
Packit 1e8aac
                  create_command_property_list (gnew_parent, saved_props);
Packit 1e8aac
Packit 1e8aac
              /* Apply the properties in an undoable way */
Packit 1e8aac
              if (prop_cmds)
Packit 1e8aac
                glade_command_set_properties_list 
Packit 1e8aac
		  (glade_widget_get_project (gparent), prop_cmds);
Packit 1e8aac
Packit 1e8aac
              /* Add "this" widget to the new parent */
Packit 1e8aac
              glade_command_add (&this_widget, gnew_parent, NULL, project, FALSE);
Packit 1e8aac
Packit 1e8aac
              glade_command_pop_group ();
Packit 1e8aac
            }
Packit 1e8aac
          else
Packit 1e8aac
	    {
Packit 1e8aac
              glade_command_pop_group ();
Packit 1e8aac
Packit 1e8aac
              /* Undo delete command
Packit 1e8aac
               * FIXME: this will leave the "Adding parent..." comand in the
Packit 1e8aac
               * redo list, which I think its better than leaving it in the
Packit 1e8aac
               * undo list by using glade_command_add() to add the widget back
Packit 1e8aac
               * to the original parent.
Packit 1e8aac
               * Ideally we need a way to remove a redo item from the project or
Packit 1e8aac
               * simply do not let the user cancel a widget creation!
Packit 1e8aac
               */
Packit 1e8aac
	      glade_project_undo (project);
Packit 1e8aac
	    }
Packit 1e8aac
Packit 1e8aac
          g_list_foreach (saved_props, (GFunc) g_object_unref, NULL);
Packit 1e8aac
          g_list_free (saved_props);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (action_path, "sizegroup_add") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      /* Ignore dummy */
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (action_path, "clear_properties") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      glade_editor_reset_dialog_run (gtk_widget_get_toplevel (GTK_WIDGET (object)), gwidget);
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (action_path, "read_documentation") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      glade_app_search_docs (glade_widget_adaptor_get_book (adaptor),
Packit 1e8aac
                             glade_widget_adaptor_get_name (adaptor),
Packit 1e8aac
                             NULL);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor,
Packit 1e8aac
                                                    object, action_path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static GList *
Packit 1e8aac
list_sizegroups (GladeWidget * gwidget)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project = glade_widget_get_project (gwidget);
Packit 1e8aac
  GList *groups = NULL;
Packit 1e8aac
  const GList *list;
Packit 1e8aac
Packit 1e8aac
  for (list = glade_project_get_objects (project); list; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeWidget *iter = glade_widget_get_from_gobject (list->data);
Packit 1e8aac
      if (GTK_IS_SIZE_GROUP (glade_widget_get_object (iter)))
Packit 1e8aac
        groups = g_list_prepend (groups, iter);
Packit 1e8aac
    }
Packit 1e8aac
  return g_list_reverse (groups);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_gtk_widget_add2group_cb (GtkMenuItem * item, GladeWidget * gwidget)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *group =
Packit 1e8aac
      g_object_get_data (G_OBJECT (item), "glade-group-widget");
Packit 1e8aac
  GladeWidgetAdaptor *adaptor =
Packit 1e8aac
      glade_widget_adaptor_get_by_type (GTK_TYPE_SIZE_GROUP);
Packit 1e8aac
  GList *widget_list = NULL, *new_list;
Packit 1e8aac
  GladeProperty *property;
Packit 1e8aac
  const gchar *current_name;
Packit 1e8aac
  const gchar *size_group_name = NULL;
Packit 1e8aac
  gchar *widget_name;
Packit 1e8aac
Packit 1e8aac
  /* Display "(unnamed)" for unnamed size groups */
Packit 1e8aac
  if (group)
Packit 1e8aac
    {
Packit 1e8aac
      size_group_name = glade_widget_get_name (group);
Packit 1e8aac
      if (g_str_has_prefix (size_group_name, GLADE_UNNAMED_PREFIX))
Packit 1e8aac
	size_group_name = _("(unnamed)");
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Ensure the widget has a name if it's going to be referred to by a size group */
Packit 1e8aac
  current_name = glade_widget_get_name (gwidget);
Packit 1e8aac
  if (g_str_has_prefix (current_name, GLADE_UNNAMED_PREFIX))
Packit 1e8aac
    widget_name = glade_project_new_widget_name (glade_widget_get_project (gwidget), NULL,
Packit 1e8aac
						 glade_widget_adaptor_get_generic_name (glade_widget_get_adaptor (gwidget)));
Packit 1e8aac
  else
Packit 1e8aac
    widget_name = g_strdup (current_name);
Packit 1e8aac
Packit 1e8aac
  if (group)
Packit 1e8aac
    glade_command_push_group (_("Adding %s to Size Group %s"),
Packit 1e8aac
			      widget_name,
Packit 1e8aac
                              size_group_name);
Packit 1e8aac
  else
Packit 1e8aac
    glade_command_push_group (_("Adding %s to a new Size Group"),
Packit 1e8aac
                              widget_name);
Packit 1e8aac
Packit 1e8aac
  glade_command_set_name (gwidget, widget_name);
Packit 1e8aac
Packit 1e8aac
  if (!group)
Packit 1e8aac
    /* Cant cancel a size group */
Packit 1e8aac
    group =
Packit 1e8aac
        glade_command_create (adaptor, NULL, NULL,
Packit 1e8aac
                              glade_widget_get_project (gwidget));
Packit 1e8aac
Packit 1e8aac
  property = glade_widget_get_property (group, "widgets");
Packit 1e8aac
  glade_property_get (property, &widget_list);
Packit 1e8aac
  new_list = g_list_copy (widget_list);
Packit 1e8aac
  if (!g_list_find (widget_list, glade_widget_get_object (gwidget)))
Packit 1e8aac
    new_list = g_list_append (new_list, glade_widget_get_object (gwidget));
Packit 1e8aac
  glade_command_set_property (property, new_list);
Packit 1e8aac
Packit 1e8aac
  g_list_free (new_list);
Packit 1e8aac
  g_free (widget_name);
Packit 1e8aac
Packit 1e8aac
  glade_command_pop_group ();
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
GtkWidget *
Packit 1e8aac
glade_gtk_widget_action_submenu (GladeWidgetAdaptor * adaptor,
Packit 1e8aac
                                 GObject * object, const gchar * action_path)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
Packit 1e8aac
  GList *groups, *list;
Packit 1e8aac
Packit 1e8aac
  if (strcmp (action_path, "sizegroup_add") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      GtkWidget *menu = gtk_menu_new ();
Packit 1e8aac
      GtkWidget *separator, *item;
Packit 1e8aac
      GladeWidget *group;
Packit 1e8aac
      const gchar *size_group_name;
Packit 1e8aac
Packit 1e8aac
      if ((groups = list_sizegroups (gwidget)) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          for (list = groups; list; list = list->next)
Packit 1e8aac
            {
Packit 1e8aac
              group = list->data;
Packit 1e8aac
Packit 1e8aac
	      size_group_name = glade_widget_get_name (group);
Packit 1e8aac
	      if (g_str_has_prefix (size_group_name, GLADE_UNNAMED_PREFIX))
Packit 1e8aac
		size_group_name = _("(unnamed)");
Packit 1e8aac
Packit 1e8aac
	      item = gtk_menu_item_new_with_label (size_group_name);
Packit 1e8aac
Packit 1e8aac
              g_object_set_data (G_OBJECT (item), "glade-group-widget", group);
Packit 1e8aac
              g_signal_connect (G_OBJECT (item), "activate",
Packit 1e8aac
                                G_CALLBACK (glade_gtk_widget_add2group_cb),
Packit 1e8aac
                                gwidget);
Packit 1e8aac
Packit 1e8aac
              gtk_widget_show (item);
Packit 1e8aac
              gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
Packit 1e8aac
            }
Packit 1e8aac
          g_list_free (groups);
Packit 1e8aac
Packit 1e8aac
          separator = gtk_menu_item_new ();
Packit 1e8aac
          gtk_menu_shell_append (GTK_MENU_SHELL (menu), separator);
Packit 1e8aac
          gtk_widget_show (separator);
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      /* Add trailing new... item */
Packit 1e8aac
      item = gtk_menu_item_new_with_label (_("New Size Group"));
Packit 1e8aac
      g_signal_connect (G_OBJECT (item), "activate",
Packit 1e8aac
                        G_CALLBACK (glade_gtk_widget_add2group_cb), gwidget);
Packit 1e8aac
Packit 1e8aac
      gtk_widget_show (item);
Packit 1e8aac
      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
Packit 1e8aac
Packit 1e8aac
      return menu;
Packit 1e8aac
    }
Packit 1e8aac
  else if (GWA_GET_CLASS (G_TYPE_OBJECT)->action_submenu)
Packit 1e8aac
    return GWA_GET_CLASS (G_TYPE_OBJECT)->action_submenu (adaptor,
Packit 1e8aac
                                                          object, action_path);
Packit 1e8aac
Packit 1e8aac
  return NULL;
Packit 1e8aac
}