From 2744d848964e0983be6a90be92e50bb110215b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 2 Feb 2011 17:22:34 +0100 Subject: Introduce LdDiagramConnection. --- CMakeLists.txt | 2 + config.h.in | 7 + liblogdiag/ld-diagram-connection.c | 333 +++++++++++++++++++++++++++++++++++++ liblogdiag/ld-diagram-connection.h | 64 +++++++ liblogdiag/ld-diagram-object.c | 9 - liblogdiag/ld-diagram.c | 4 + liblogdiag/ld-diagram.h | 8 - liblogdiag/liblogdiag.h | 1 + 8 files changed, 411 insertions(+), 17 deletions(-) create mode 100644 liblogdiag/ld-diagram-connection.c create mode 100644 liblogdiag/ld-diagram-connection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c83c36..a7e62ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ set (liblogdiag_SOURCES liblogdiag/ld-diagram.c liblogdiag/ld-diagram-object.c liblogdiag/ld-diagram-symbol.c + liblogdiag/ld-diagram-connection.c liblogdiag/ld-canvas.c liblogdiag/ld-library.c liblogdiag/ld-library-toolbar.c @@ -130,6 +131,7 @@ set (liblogdiag_HEADERS liblogdiag/ld-diagram.h liblogdiag/ld-diagram-object.h liblogdiag/ld-diagram-symbol.h + liblogdiag/ld-diagram-connection.h liblogdiag/ld-canvas.h liblogdiag/ld-library.h liblogdiag/ld-library-toolbar.h diff --git a/config.h.in b/config.h.in index 9f15b52..43b5f30 100644 --- a/config.h.in +++ b/config.h.in @@ -50,5 +50,12 @@ #endif #endif /* ! HAVE_SANE___RESTRICT */ +/* We have to remove nodes first due to a bug in json-glib. */ +#define json_object_set_member(object, name, node) \ + G_STMT_START { \ + json_object_remove_member ((object), (name)); \ + json_object_set_member ((object), (name), (node)); \ + } G_STMT_END + #endif /* __CONFIG_H__ */ 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 + +#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); +} + diff --git a/liblogdiag/ld-diagram-connection.h b/liblogdiag/ld-diagram-connection.h new file mode 100644 index 0000000..c85aa5b --- /dev/null +++ b/liblogdiag/ld-diagram-connection.h @@ -0,0 +1,64 @@ +/* + * ld-diagram-connection.h + * + * This file is a part of logdiag. + * Copyright Přemysl Janouch 2011. All rights reserved. + * + * See the file LICENSE for licensing information. + * + */ + +#ifndef __LD_DIAGRAM_CONNECTION_H__ +#define __LD_DIAGRAM_CONNECTION_H__ + +G_BEGIN_DECLS + + +#define LD_TYPE_DIAGRAM_CONNECTION (ld_diagram_connection_get_type ()) +#define LD_DIAGRAM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), LD_TYPE_DIAGRAM_CONNECTION, LdDiagramConnection)) +#define LD_DIAGRAM_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST \ + ((klass), LD_TYPE_DIAGRAM_CONNECTION, LdDiagramConnectionClass)) +#define LD_IS_DIAGRAM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), LD_TYPE_DIAGRAM_CONNECTION)) +#define LD_IS_DIAGRAM_CONNECTION_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE \ + ((klass), LD_TYPE_DIAGRAM_CONNECTION)) +#define LD_DIAGRAM_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), LD_DIAGRAM_CONNECTION, LdDiagramConnectionClass)) + +typedef struct _LdDiagramConnection LdDiagramConnection; +typedef struct _LdDiagramConnectionPrivate LdDiagramConnectionPrivate; +typedef struct _LdDiagramConnectionClass LdDiagramConnectionClass; + + +/** + * LdDiagramConnection: + */ +struct _LdDiagramConnection +{ +/*< private >*/ + LdDiagramObject parent_instance; +}; + +/** + * LdDiagramConnectionClass: + */ +struct _LdDiagramConnectionClass +{ +/*< private >*/ + LdDiagramObjectClass parent_class; +}; + + +GType ld_diagram_connection_get_type (void) G_GNUC_CONST; + +LdDiagramConnection *ld_diagram_connection_new (JsonObject *storage); +LdPointArray *ld_diagram_connection_get_points (LdDiagramConnection *self); +void ld_diagram_connection_set_points (LdDiagramConnection *self, + const LdPointArray *points); + + +G_END_DECLS + +#endif /* ! __LD_DIAGRAM_CONNECTION_H__ */ + diff --git a/liblogdiag/ld-diagram-object.c b/liblogdiag/ld-diagram-object.c index 7c83f34..e39f89c 100644 --- a/liblogdiag/ld-diagram-object.c +++ b/liblogdiag/ld-diagram-object.c @@ -312,15 +312,6 @@ ld_diagram_object_get_data_default: g_object_set_property (G_OBJECT (self), name, data); } -/* We have to remove it first due to a bug in json-glib. */ -#define json_object_set_member(object, name, node) \ - G_STMT_START \ - { \ - json_object_remove_member (object, name); \ - json_object_set_member (object, name, node); \ - } \ - G_STMT_END - /** * ld_diagram_object_set_data_for_param: * @self: an #LdDiagramObject object. diff --git a/liblogdiag/ld-diagram.c b/liblogdiag/ld-diagram.c index ba20762..18a0993 100644 --- a/liblogdiag/ld-diagram.c +++ b/liblogdiag/ld-diagram.c @@ -525,6 +525,8 @@ deserialize_object (JsonObject *object_storage) type = json_node_get_string (object_type_node); if (!g_strcmp0 ("symbol", type)) return LD_DIAGRAM_OBJECT (ld_diagram_symbol_new (object_storage)); + if (!g_strcmp0 ("connection", type)) + return LD_DIAGRAM_OBJECT (ld_diagram_connection_new (object_storage)); deserialize_object_default: /* Anything we can't identify is just an indefinite object. */ @@ -576,6 +578,8 @@ get_object_class_string (GType type) { if (type == LD_TYPE_DIAGRAM_SYMBOL) return "symbol"; + if (type == LD_TYPE_DIAGRAM_CONNECTION) + return "connection"; if (type != LD_TYPE_DIAGRAM_OBJECT) /* We don't know our own type, that's just plain wrong. */ g_warn_if_reached (); diff --git a/liblogdiag/ld-diagram.h b/liblogdiag/ld-diagram.h index 52f0453..1f1b573 100644 --- a/liblogdiag/ld-diagram.h +++ b/liblogdiag/ld-diagram.h @@ -110,14 +110,6 @@ void ld_diagram_select_all (LdDiagram *self); void ld_diagram_unselect (LdDiagram *self, LdDiagramObject *object); void ld_diagram_unselect_all (LdDiagram *self); -/* -GList *ld_diagram_get_connections (LdDiagram *self); -void ld_diagram_connection_add (LdDiagram *self, - LdConnection *connection, gint pos); -void ld_diagram_connection_remove (LdDiagram *self, - LdConnection *connection); -*/ - G_END_DECLS diff --git a/liblogdiag/liblogdiag.h b/liblogdiag/liblogdiag.h index 769662e..0e17e92 100644 --- a/liblogdiag/liblogdiag.h +++ b/liblogdiag/liblogdiag.h @@ -24,6 +24,7 @@ #include "ld-undo-action.h" #include "ld-diagram-object.h" #include "ld-diagram-symbol.h" +#include "ld-diagram-connection.h" #include "ld-diagram.h" #include "ld-canvas.h" -- cgit v1.2.3