aboutsummaryrefslogtreecommitdiff
path: root/liblogdiag
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2011-02-02 17:22:34 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2011-02-02 17:22:34 +0100
commit2744d848964e0983be6a90be92e50bb110215b26 (patch)
treecf8dd5a73cdd6504d1cfd9fd286dd5233a6ee0cd /liblogdiag
parent539f5378462670d10ea6500a7980f3a7f84fe0d5 (diff)
downloadlogdiag-2744d848964e0983be6a90be92e50bb110215b26.tar.gz
logdiag-2744d848964e0983be6a90be92e50bb110215b26.tar.xz
logdiag-2744d848964e0983be6a90be92e50bb110215b26.zip
Introduce LdDiagramConnection.
Diffstat (limited to 'liblogdiag')
-rw-r--r--liblogdiag/ld-diagram-connection.c333
-rw-r--r--liblogdiag/ld-diagram-connection.h64
-rw-r--r--liblogdiag/ld-diagram-object.c9
-rw-r--r--liblogdiag/ld-diagram.c4
-rw-r--r--liblogdiag/ld-diagram.h8
-rw-r--r--liblogdiag/liblogdiag.h1
6 files changed, 402 insertions, 17 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);
+}
+
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"