Introduce LdDiagramConnection.

This commit is contained in:
Přemysl Eric Janouch 2011-02-02 17:22:34 +01:00
parent 539f537846
commit 2744d84896
8 changed files with 411 additions and 17 deletions

View File

@ -114,6 +114,7 @@ set (liblogdiag_SOURCES
liblogdiag/ld-diagram.c liblogdiag/ld-diagram.c
liblogdiag/ld-diagram-object.c liblogdiag/ld-diagram-object.c
liblogdiag/ld-diagram-symbol.c liblogdiag/ld-diagram-symbol.c
liblogdiag/ld-diagram-connection.c
liblogdiag/ld-canvas.c liblogdiag/ld-canvas.c
liblogdiag/ld-library.c liblogdiag/ld-library.c
liblogdiag/ld-library-toolbar.c liblogdiag/ld-library-toolbar.c
@ -130,6 +131,7 @@ set (liblogdiag_HEADERS
liblogdiag/ld-diagram.h liblogdiag/ld-diagram.h
liblogdiag/ld-diagram-object.h liblogdiag/ld-diagram-object.h
liblogdiag/ld-diagram-symbol.h liblogdiag/ld-diagram-symbol.h
liblogdiag/ld-diagram-connection.h
liblogdiag/ld-canvas.h liblogdiag/ld-canvas.h
liblogdiag/ld-library.h liblogdiag/ld-library.h
liblogdiag/ld-library-toolbar.h liblogdiag/ld-library-toolbar.h

View File

@ -50,5 +50,12 @@
#endif #endif
#endif /* ! HAVE_SANE___RESTRICT */ #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__ */ #endif /* __CONFIG_H__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -312,15 +312,6 @@ ld_diagram_object_get_data_default:
g_object_set_property (G_OBJECT (self), name, data); 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: * ld_diagram_object_set_data_for_param:
* @self: an #LdDiagramObject object. * @self: an #LdDiagramObject object.

View File

@ -525,6 +525,8 @@ deserialize_object (JsonObject *object_storage)
type = json_node_get_string (object_type_node); type = json_node_get_string (object_type_node);
if (!g_strcmp0 ("symbol", type)) if (!g_strcmp0 ("symbol", type))
return LD_DIAGRAM_OBJECT (ld_diagram_symbol_new (object_storage)); 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: deserialize_object_default:
/* Anything we can't identify is just an indefinite object. */ /* 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) if (type == LD_TYPE_DIAGRAM_SYMBOL)
return "symbol"; return "symbol";
if (type == LD_TYPE_DIAGRAM_CONNECTION)
return "connection";
if (type != LD_TYPE_DIAGRAM_OBJECT) if (type != LD_TYPE_DIAGRAM_OBJECT)
/* We don't know our own type, that's just plain wrong. */ /* We don't know our own type, that's just plain wrong. */
g_warn_if_reached (); g_warn_if_reached ();

View File

@ -110,14 +110,6 @@ void ld_diagram_select_all (LdDiagram *self);
void ld_diagram_unselect (LdDiagram *self, LdDiagramObject *object); void ld_diagram_unselect (LdDiagram *self, LdDiagramObject *object);
void ld_diagram_unselect_all (LdDiagram *self); 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 G_END_DECLS

View File

@ -24,6 +24,7 @@
#include "ld-undo-action.h" #include "ld-undo-action.h"
#include "ld-diagram-object.h" #include "ld-diagram-object.h"
#include "ld-diagram-symbol.h" #include "ld-diagram-symbol.h"
#include "ld-diagram-connection.h"
#include "ld-diagram.h" #include "ld-diagram.h"
#include "ld-canvas.h" #include "ld-canvas.h"