diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2011-02-02 17:22:34 +0100 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2011-02-02 17:22:34 +0100 | 
| commit | 2744d848964e0983be6a90be92e50bb110215b26 (patch) | |
| tree | cf8dd5a73cdd6504d1cfd9fd286dd5233a6ee0cd /liblogdiag/ld-diagram-connection.c | |
| parent | 539f5378462670d10ea6500a7980f3a7f84fe0d5 (diff) | |
| download | logdiag-2744d848964e0983be6a90be92e50bb110215b26.tar.gz logdiag-2744d848964e0983be6a90be92e50bb110215b26.tar.xz logdiag-2744d848964e0983be6a90be92e50bb110215b26.zip | |
Introduce LdDiagramConnection.
Diffstat (limited to 'liblogdiag/ld-diagram-connection.c')
| -rw-r--r-- | liblogdiag/ld-diagram-connection.c | 333 | 
1 files changed, 333 insertions, 0 deletions
| diff --git a/liblogdiag/ld-diagram-connection.c b/liblogdiag/ld-diagram-connection.c new file mode 100644 index 0000000..04e5888 --- /dev/null +++ b/liblogdiag/ld-diagram-connection.c @@ -0,0 +1,333 @@ +/* + * ld-diagram-connection.c + * + * This file is a part of logdiag. + * Copyright Přemysl Janouch 2011. All rights reserved. + * + * See the file LICENSE for licensing information. + * + */ + +#include <string.h> + +#include "liblogdiag.h" +#include "config.h" + + +/** + * SECTION:ld-diagram-connection + * @short_description: A connection object + * @see_also: #LdDiagramObject + * + * #LdDiagramConnection is an implementation of #LdDiagramObject. + */ + +typedef struct _SetPointsActionData SetPointsActionData; + +/* + * SetPointsActionData: + * @self: the object this action has happened on. + * @old_node: the old node. + * @new_node: the new node. + */ +struct _SetPointsActionData +{ +	LdDiagramConnection *self; +	JsonNode *old_node; +	JsonNode *new_node; +}; + +enum +{ +	PROP_0, +	PROP_POINTS +}; + +static void ld_diagram_connection_get_property (GObject *object, +	guint property_id, GValue *value, GParamSpec *pspec); +static void ld_diagram_connection_set_property (GObject *object, +	guint property_id, const GValue *value, GParamSpec *pspec); + +static gboolean read_point_node (JsonNode *node, LdPoint *point); +static gboolean read_double_node (JsonNode *node, gdouble *value); + +static void on_set_points_undo (gpointer user_data); +static void on_set_points_redo (gpointer user_data); +static void on_set_points_destroy (gpointer user_data); + + +G_DEFINE_TYPE (LdDiagramConnection, ld_diagram_connection, +	LD_TYPE_DIAGRAM_OBJECT); + +static void +ld_diagram_connection_class_init (LdDiagramConnectionClass *klass) +{ +	GObjectClass *object_class; +	GParamSpec *pspec; + +	object_class = G_OBJECT_CLASS (klass); +	object_class->get_property = ld_diagram_connection_get_property; +	object_class->set_property = ld_diagram_connection_set_property; + +/** + * LdDiagramConnection:points: + * + * Points defining this connection. + */ +	pspec = g_param_spec_boxed ("points", "Points", +		"Points defining this connection.", +		LD_TYPE_POINT_ARRAY, G_PARAM_READWRITE); +	g_object_class_install_property (object_class, PROP_POINTS, pspec); +} + +static void +ld_diagram_connection_init (LdDiagramConnection *self) +{ +} + +static void +ld_diagram_connection_get_property (GObject *object, guint property_id, +	GValue *value, GParamSpec *pspec) +{ +	LdDiagramConnection *self; + +	self = LD_DIAGRAM_CONNECTION (object); +	switch (property_id) +	{ +		LdPointArray *points; + +	case PROP_POINTS: +		points = ld_diagram_connection_get_points (self); +		g_value_set_boxed_take_ownership (value, points); +		break; +	default: +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +	} +} + +static void +ld_diagram_connection_set_property (GObject *object, guint property_id, +	const GValue *value, GParamSpec *pspec) +{ +	LdDiagramConnection *self; + +	self = LD_DIAGRAM_CONNECTION (object); +	switch (property_id) +	{ +	case PROP_POINTS: +		ld_diagram_connection_set_points (self, g_value_get_boxed (value)); +		break; +	default: +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +	} +} + + +/** + * ld_diagram_connection_new: + * @storage: a storage backend. + * + * Return value: a new #LdDiagramConnection object. + */ +LdDiagramConnection * +ld_diagram_connection_new (JsonObject *storage) +{ +	LdDiagramConnection *self; + +	self = g_object_new (LD_TYPE_DIAGRAM_CONNECTION, "storage", storage, NULL); +	return self; +} + +#define WARN_NODE_TYPE(node, type) \ +	G_STMT_START { \ +		g_warning ("%s: unable to read a value of type `%s' from node" \ +			" of type `%s'", G_STRLOC, g_type_name (type), \ +			json_node_type_name (node)); \ +	} G_STMT_END + +/** + * ld_diagram_connection_get_points: + * @self: an #LdDiagramConnection object. + * + * Get points defining this connection. Coordinates of the points are relative + * to the inherited #LdDiagramObject:x and #LdDiagramObject:y properties. + * + * Return value: (transfer full): a point array. + */ +LdPointArray * +ld_diagram_connection_get_points (LdDiagramConnection *self) +{ +	LdPointArray *points; +	JsonObject *storage; +	JsonNode *node; +	JsonArray *array; +	GList *point_node_list, *iter; + +	g_return_val_if_fail (LD_IS_DIAGRAM_CONNECTION (self), NULL); + +	storage = ld_diagram_object_get_storage (LD_DIAGRAM_OBJECT (self)); +	node = json_object_get_member (storage, "points"); +	if (!node || json_node_is_null (node)) +		return ld_point_array_new (0); +	if (!JSON_NODE_HOLDS_ARRAY (node)) +	{ +		WARN_NODE_TYPE (node, LD_TYPE_POINT_ARRAY); +		return ld_point_array_new (0); +	} + +	array = json_node_get_array (node); +	point_node_list = json_array_get_elements (array); +	points = ld_point_array_new (json_array_get_length (array)); + +	points->num_points = 0; +	for (iter = point_node_list; iter; iter = g_list_next (iter)) +	{ +		if (read_point_node (iter->data, &points->points[points->num_points])) +			points->num_points++; +	} +	return points; +} + +static gboolean +read_point_node (JsonNode *node, LdPoint *point) +{ +	JsonArray *array; +	JsonNode *x_node, *y_node; + +	g_return_val_if_fail (node != NULL, FALSE); +	g_return_val_if_fail (point != NULL, FALSE); + +	if (!JSON_NODE_HOLDS_ARRAY (node)) +	{ +		WARN_NODE_TYPE (node, LD_TYPE_POINT); +		return FALSE; +	} +	array = json_node_get_array (node); +	if (json_array_get_length (array) < 2) +	{ +		g_warning ("%s: too few values for a point", G_STRLOC); +		return FALSE; +	} + +	x_node = json_array_get_element (array, 0); +	y_node = json_array_get_element (array, 1); + +	return read_double_node (x_node, &point->x) +		&& read_double_node (y_node, &point->y); +} + +static gboolean +read_double_node (JsonNode *node, gdouble *value) +{ +	GValue double_value, json_value; + +	g_return_val_if_fail (node != NULL, FALSE); +	g_return_val_if_fail (value != NULL, FALSE); + +	if (!JSON_NODE_HOLDS_VALUE (node) || !g_value_type_transformable +		(json_node_get_value_type (node), G_TYPE_DOUBLE)) +	{ +		WARN_NODE_TYPE (node, G_TYPE_DOUBLE); +		return FALSE; +	} + +	memset (&json_value, 0, sizeof (GValue)); +	memset (&double_value, 0, sizeof (GValue)); + +	json_node_get_value (node, &json_value); +	g_value_init (&double_value, G_TYPE_DOUBLE); +	g_value_transform (&json_value, &double_value); +	*value = g_value_get_double (&double_value); + +	g_value_unset (&json_value); +	g_value_unset (&double_value); +	return TRUE; +} + +/** + * ld_diagram_connection_set_points: + * @self: an #LdDiagramConnection object. + * @points: a point array. + * + * Set the points defining this connection. + */ +void +ld_diagram_connection_set_points (LdDiagramConnection *self, +	const LdPointArray *points) +{ +	LdUndoAction *action; +	SetPointsActionData *action_data; +	JsonNode *node; +	JsonObject *storage; +	JsonArray *array, *point_array; +	guint i; + +	g_return_if_fail (LD_IS_DIAGRAM_CONNECTION (self)); +	g_return_if_fail (points != NULL); + +	storage = ld_diagram_object_get_storage (LD_DIAGRAM_OBJECT (self)); +	array = json_array_new (); +	for (i = 0; i < points->num_points; i++) +	{ +		point_array = json_array_new (); +		json_array_add_double_element (point_array, points->points[i].x); +		json_array_add_double_element (point_array, points->points[i].y); +		json_array_add_array_element (array, point_array); +	} + +	action_data = g_slice_new (SetPointsActionData); +	action_data->self = g_object_ref (self); + +	node = json_object_get_member (storage, "points"); +	action_data->old_node = node ? json_node_copy (node) : NULL; + +	node = json_node_new (JSON_NODE_ARRAY); +	json_node_set_array (node, array); +	action_data->new_node = json_node_copy (node); + +	json_object_set_member (storage, "points", node); + +	action = ld_undo_action_new (on_set_points_undo, on_set_points_redo, +		on_set_points_destroy, action_data); +	ld_diagram_object_changed (LD_DIAGRAM_OBJECT (self), action); +	g_object_unref (action); +} + +static void +on_set_points_undo (gpointer user_data) +{ +	SetPointsActionData *data; +	JsonObject *storage; + +	data = user_data; +	storage = ld_diagram_object_get_storage (LD_DIAGRAM_OBJECT (data->self)); + +	json_object_set_member (storage, "points", json_node_copy (data->old_node)); +} + +static void +on_set_points_redo (gpointer user_data) +{ +	SetPointsActionData *data; +	JsonObject *storage; + +	data = user_data; +	storage = ld_diagram_object_get_storage (LD_DIAGRAM_OBJECT (data->self)); + +	json_object_set_member (storage, "points", json_node_copy (data->new_node)); +} + +static void +on_set_points_destroy (gpointer user_data) +{ +	SetPointsActionData *data; + +	data = user_data; +	g_object_unref (data->self); +	if (data->old_node) +		json_node_free (data->old_node); +	if (data->new_node) +		json_node_free (data->new_node); +	g_slice_free (SetPointsActionData, data); +} + | 
