/*
* Copyright (C) 2011-2013 Karlsruhe Institute of Technology
*
* This file is part of Ufo.
*
* 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 3 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 library. If not, see .
*/
#include
/**
* SECTION:ufo-node
* @Short_description: Generic node type
* @Title: UfoNode
*/
G_DEFINE_TYPE (UfoNode, ufo_node, G_TYPE_OBJECT)
#define UFO_NODE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_NODE, UfoNodePrivate))
static UfoNode *ufo_node_copy_real (UfoNode *node, GError **error);
struct _UfoNodePrivate {
UfoNode *orig;
guint total;
guint index;
gpointer label;
};
enum {
PROP_0,
N_PROPERTIES
};
UfoNode *
ufo_node_new (gpointer label)
{
UfoNode *node;
node = UFO_NODE (g_object_new (UFO_TYPE_NODE, NULL));
node->priv->label = label;
return node;
}
/**
* ufo_node_get_label:
* @node: A #UfoNode
*
* Get arbitrary label data of @node.
*
* Returns: (transfer none): The label of @node.
*/
gpointer
ufo_node_get_label (UfoNode *node)
{
g_return_val_if_fail (UFO_IS_NODE (node), NULL);
return node->priv->label;
}
static void
copy_properties (GObject *dst,
GObject *src)
{
GParamSpec **props;
guint n_props;
props = g_object_class_list_properties (G_OBJECT_GET_CLASS (src), &n_props);
for (guint i = 0; i < n_props; i++) {
if (props[i]->flags & G_PARAM_WRITABLE) {
GValue value = {0};
g_value_init (&value, props[i]->value_type);
g_object_get_property (src, props[i]->name, &value);
if (UFO_IS_NODE_CLASS (&(props[i]->value_type))) {
GObject *prop_object;
prop_object = G_OBJECT (ufo_node_copy_real (UFO_NODE (g_value_get_object (&value)), NULL));
g_object_force_floating (prop_object);
g_value_take_object (&value, prop_object);
}
g_object_set_property (dst, props[i]->name, &value);
}
}
g_free (props);
}
static UfoNode *
ufo_node_copy_real (UfoNode *node,
GError **error)
{
UfoNode *orig;
UfoNode *copy;
copy = UFO_NODE (g_object_new (G_OBJECT_TYPE (node), NULL));
orig = node->priv->orig;
copy_properties (G_OBJECT (copy), G_OBJECT (orig));
copy->priv->orig = orig;
copy->priv->label = orig->priv->label;
copy->priv->index = orig->priv->total;
orig->priv->total++;
return copy;
}
static gboolean
ufo_node_equal_real (UfoNode *n1,
UfoNode *n2)
{
g_return_val_if_fail (UFO_IS_NODE (n1) && UFO_IS_NODE (n2), FALSE);
/* FIXME: When done we should just check if the types match */
return n1 == n2;
}
/**
* ufo_node_copy:
* @node: A #UfoNode
* @error: Location for an error
*
* Get a copy of @node. How "deep" the copy is, depends on the inherited
* implementation of @node. The copy receives an new index and the total amount
* of nodes is increased by one.
*
* Returns: (transfer full): Copy of @node.
*/
UfoNode *
ufo_node_copy (UfoNode *node,
GError **error)
{
return UFO_NODE_GET_CLASS (node)->copy (node, error);
}
/**
* ufo_node_get_index:
* @node: A #UfoNode
*
* Get the index of this node. When a graph is expanded, nodes are copied. The
* original node has index 1, all successive copies receive a monotonous
* increasing index. The total amount of copied nodes can be queried with
* ufo_node_get_total().
*
* Returns: The index of @node.
*/
guint
ufo_node_get_index (UfoNode *node)
{
g_return_val_if_fail (UFO_IS_NODE (node), 0);
return node->priv->index;
}
/**
* ufo_node_get_total:
* @node: A #UfoNode
*
* Get the total amount of copied nodes.
*
* Returns: The number of copied nodes.
*/
guint
ufo_node_get_total (UfoNode *node)
{
g_return_val_if_fail (UFO_IS_NODE (node), 0);
return node->priv->orig->priv->total;
}
gboolean
ufo_node_equal (UfoNode *n1,
UfoNode *n2)
{
return UFO_NODE_GET_CLASS (n1)->equal (n1, n2);
}
static void
ufo_node_class_init (UfoNodeClass *klass)
{
klass->copy = ufo_node_copy_real;
klass->equal = ufo_node_equal_real;
g_type_class_add_private (klass, sizeof(UfoNodePrivate));
}
static void
ufo_node_init (UfoNode *self)
{
UfoNodePrivate *priv;
self->priv = priv = UFO_NODE_GET_PRIVATE (self);
priv->orig = self;
priv->label = NULL;
priv->total = 1;
priv->index = 0;
}