• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

作図ソフト dia の改良版


Commit MetaInfo

Revision414c14ea85d8f81fbc0b3392ba3ceaaaed0486d1 (tree)
Time2007-03-27 05:18:26
AuthorHans Breuer <hans@breu...>
CommiterHans Breuer

Log Message

dia/lib bindings with the help of SWIG, for details see:

2007-03-26 Hans Breuer <hans@breuer.org>

* bindings/* : dia/lib bindings with the help of SWIG, for details
see: http://mail.gnome.org/archives/dia-list/2007-March/msg00092.html

svn path=/trunk/; revision=3651

Change Summary

Incremental Difference

--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
1+2007-03-26 Hans Breuer <hans@breuer.org>
2+
3+ * bindings/* : dia/lib bindings with the help of SWIG, for details
4+ see: http://mail.gnome.org/archives/dia-list/2007-March/msg00092.html
5+
16 2007-03-25 Lars Clausen <lars@raeder.dk>
27
38 * NEWS:
--- /dev/null
+++ b/bindings/Doxyfile
@@ -0,0 +1,26 @@
1+# Doxyfile 1.4.6
2+PROJECT_NAME = "Dia Bindings"
3+OUTPUT_DIRECTORY = .
4+VERBATIM_HEADERS = NO
5+#SHOW_INCLUDE_FILES = YES
6+#GENERATE_TODOLIST = YES
7+#GENERATE_TESTLIST = YES
8+DETAILS_AT_TOP = YES
9+INPUT = .
10+FILE_PATTERNS = *.h *.cpp
11+EXCLUDE = dia-python.cpp
12+GENERATE_HTML = YES
13+HTML_OUTPUT = html
14+
15+GENERATE_LATEX = NO
16+GENERATE_RTF = NO
17+GENERATE_MAN = NO
18+
19+HAVE_DOT = YES
20+CLASS_GRAPH = YES
21+COLLABORATION_GRAPH = YES
22+UML_LOOK = YES
23+CALL_GRAPH = YES
24+INCLUDE_GRAPH = NO
25+INCLUDED_BY_GRAPH = NO
26+GRAPHICAL_HIERARCHY = YES
--- /dev/null
+++ b/bindings/dia-bindings.h
@@ -0,0 +1,18 @@
1+/*
2+ * Copyright 2007, Hans Breuer, GPL, see COPYING
3+ */
4+#ifndef DIA__BINDINGS_H
5+#define DIA__BINDINGS_H
6+/*!
7+ * \mainpage Dia Bindings with C++ and SWIG
8+ *
9+ * This project provides language bindings for some <a href="http://www.gnome.org/projects/dia/">Dia</a>
10+ * classes. Where ever possible/feasible the new bindings resemble the preexisting
11+ * <a href="http://www.gnome.org/projects/dia/python.html">Dia Python Bindings</a>. But other than that
12+ * this project should allow to bind Dia to various languages. Potentially supported langauges are everything
13+ * supported by <a href="http://www.swig.org">SWIG</a>.
14+ *
15+ *
16+ */
17+
18+#endif
--- /dev/null
+++ b/bindings/dia-connections.cpp
@@ -0,0 +1,117 @@
1+/*
2+ * C++ implementation of Dia Connections - just proxies
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+#include "object.h"
21+
22+#include "dia-object.h"
23+
24+#include "dia-connections.h"
25+#include "dia-diagramdata.h"
26+
27+#include "diagramdata.h"
28+
29+dia::ConnectionPoint::ConnectionPoint (::ConnectionPoint* p) : self(p), connected(&p->connected)
30+{
31+}
32+
33+dia::ConnectionPoint::~ConnectionPoint ()
34+{
35+}
36+//! read-only attribute: placement
37+::_Point
38+dia::ConnectionPoint::pos () const
39+{
40+ ::_Point dummy = {0, 0};
41+ g_return_val_if_fail (self, dummy);
42+ return self->pos;
43+}
44+//! the object this is belonging to. To follow a connection
45+//! you go from Handle.connected_to -> ConnectionPoint.object
46+dia::Object*
47+dia::ConnectionPoint::get_object () const
48+{
49+ g_return_val_if_fail (self, 0);
50+ return new dia::Object(self->object);
51+}
52+
53+dia::Connections::Connections (::DiaObject* o) : object(o)
54+{
55+}
56+dia::Connections::~Connections ()
57+{
58+}
59+//! is there a property of this name
60+int
61+dia::Connections::len () const
62+{
63+ if (object)
64+ object->num_connections;
65+ return 0;
66+}
67+//! return back a single property
68+dia::ConnectionPoint*
69+dia::Connections::getitem (int n) const
70+{
71+ g_return_val_if_fail (object, 0);
72+ if (n < 0 || n >= object->num_connections)
73+ return 0;
74+ return new dia::ConnectionPoint (object->connections[n]);
75+}
76+//! \todo find a way to SWIG pick up the accessors as attributes w/o
77+//! remaning the accessor and
78+//! %attribute(dia::Handle, dia::ConnectionPoint*, connected_to, get_connected_to);
79+const dia::ConnectionPoint*
80+dia::Handle::get_connected_to() const
81+{
82+ g_return_val_if_fail (self, 0);
83+ if (!self->connected_to)
84+ return 0;
85+ return new ConnectionPoint(self->connected_to);
86+}
87+void
88+dia::Handle::connect (dia::ConnectionPoint* cp)
89+{
90+ g_return_if_fail (self != NULL);
91+ g_return_if_fail (owner != NULL);
92+ object_connect (owner, self, cp->Self());
93+}
94+//! construct from owner
95+dia::Handles::Handles (::DiaObject* o) : object(o)
96+{
97+}
98+//! destroy
99+dia::Handles::~Handles ()
100+{
101+}
102+//! how many contained
103+int
104+dia::Handles::len () const
105+{
106+ g_return_val_if_fail (object != NULL, 0);
107+ return object->num_handles;
108+}
109+//! return back a single property
110+dia::Handle*
111+dia::Handles::getitem (int n) const
112+{
113+ g_return_val_if_fail (object, 0);
114+ if (n < 0 || n >= object->num_handles)
115+ return 0;
116+ return new dia::Handle (object->handles[n], object);
117+}
--- /dev/null
+++ b/bindings/dia-connections.h
@@ -0,0 +1,106 @@
1+/*
2+ * C++ interface of Dia Connections - just to have something clean to wrap
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__CONNECTIONS_H
7+#define DIA__CONNECTIONS_H
8+
9+#include "dia-diagramdata.h"
10+
11+namespace dia {
12+
13+// forward declare
14+class Object;
15+
16+/*!
17+ * \brief Where a connection and an object meet there is a ConnectionPoint
18+ *
19+ * The ConnectionPoint is one part to do a connection. The other part is Handle.
20+ */
21+class ConnectionPoint
22+{
23+public :
24+ //! construct from underlying data type
25+ ConnectionPoint (::ConnectionPoint* p);
26+ //! destruct
27+ ~ConnectionPoint ();
28+
29+ //! FIXME: trying to be compatible
30+ //! read-only attribute;
31+ const dia::Objects connected;
32+ //! read-only attribute: placement
33+ _Point pos () const;
34+ //! the object this is belonging to. To follow a connection you go from Handle.connected_to -> ConnectionPoint.object
35+ Object* get_object () const;
36+
37+ //! get on the underlying object
38+ ::ConnectionPoint* Self() const { return self; }
39+private :
40+ ::ConnectionPoint* self;
41+};
42+
43+/*!
44+ * \brief A container for ConnectionPoints, provides array access to them
45+ *
46+ */
47+class Connections
48+{
49+public :
50+ //! construct from owning Object
51+ Connections (::DiaObject*);
52+ //! destroy the wrapper, not the underlying type
53+ ~Connections ();
54+ /* accessors like Python sequence */
55+ //! how many contained
56+ int len () const;
57+ //! return back a single property
58+ ConnectionPoint* getitem (int) const;
59+
60+private :
61+ ::DiaObject* object; //!< the owner of the connections
62+};
63+/*!
64+ * \brief With a Handle you have a grip on an Object
65+ *
66+ * Together with ConnectionPoint a Handle allows to connect objects.
67+ */
68+class Handle
69+{
70+public :
71+ //! construct from wrapped
72+ Handle (_Handle* h, _DiaObject* o) : self(h), owner(o) {}
73+ //! indirectly delivers the object this is connected to, if at all
74+ const ConnectionPoint* get_connected_to() const;
75+ //! establish a connection to another object
76+ void connect (ConnectionPoint*);
77+
78+ //! convert to underlying
79+ ::_Handle* Self() const { return self; }
80+private :
81+ ::_Handle* self;
82+ ::_DiaObject* owner;
83+};
84+/*!
85+ * \brief Collection of Handle
86+ */
87+class Handles
88+{
89+public :
90+ //! construct from owner
91+ Handles (::DiaObject*);
92+ //! destroy
93+ ~Handles ();
94+
95+ /* array access */
96+ //! how many contained
97+ int len () const;
98+ //! return back a single one
99+ Handle* getitem (int) const;
100+
101+private :
102+ ::DiaObject* object;
103+};
104+
105+} // namespace dia
106+#endif /* DIA__CONNECTIONS_H */
--- /dev/null
+++ b/bindings/dia-diagramdata.cpp
@@ -0,0 +1,176 @@
1+/*
2+ * C++ wrapper of DiagramData - just to have something clean to wrap
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+#include "object.h"
21+#include "diagramdata.h"
22+#include <assert.h>
23+
24+#include "dia-object.h"
25+
26+#include "dia-diagramdata.h"
27+
28+//! how many contained
29+int
30+dia::Objects::len () const
31+{
32+ if (list)
33+ return g_list_length(*list);
34+ return 0;
35+}
36+//! \brief return back a single one
37+//! Together with len() getitem() allows list access. The code generator needs some
38+//! extra help to not making it an endless list. At least for Python the NULL return
39+//! was turned into None objects, we want to have only as much list elements
40+//! as there are real objects.
41+dia::Object*
42+dia::Objects::getitem (int n) const
43+{
44+ if (list && n >= 0 && n < g_list_length(*list))
45+ return new dia::Object((::DiaObject*)g_list_nth_data(*list, n));
46+ return 0;
47+}
48+
49+//! construct with underlying list of objects
50+//! \todo check ownership/lifetime of that list!
51+dia::Layer::Layer (::Layer* layer) : self(layer), _found(0)
52+{
53+ assert (self);
54+ // todo: when we allow to change the name this needs to change
55+ name = g_strdup (self->name);
56+ objects = new dia::Objects(&(layer->objects));
57+}
58+dia::Layer::~Layer ()
59+{
60+ if (_found)
61+ delete _found;
62+ if (name)
63+ g_free (const_cast<gchar*>(name));
64+ if (objects)
65+ delete const_cast<dia::Objects*>(objects);
66+}
67+void
68+dia::Layer::add_object (Object* o)
69+{
70+ g_return_if_fail (self != NULL);
71+ layer_add_object (self, o->Self());
72+}
73+void
74+dia::Layer::update_extents ()
75+{
76+ g_return_if_fail (self != NULL);
77+ layer_update_extents(self);
78+}
79+//! the object next to given point but within maxdist
80+dia::Object*
81+dia::Layer::find_closest_object (::Point* pos, double maxdist) const
82+{
83+ g_return_val_if_fail (self != NULL, 0);
84+ ::DiaObject* o = layer_find_closest_object (self, pos, maxdist);
85+ if (o)
86+ return new dia::Object (o);
87+ return 0;
88+}
89+//! a list of Object in the given rectangle
90+dia::Objects&
91+dia::Layer::find_objects_in_rectangle (::Rectangle* rect) const
92+{
93+ static GList* list = layer_find_objects_in_rectangle (self, rect);
94+ if (_found)
95+ delete _found;
96+ const_cast<Layer*>(this)->_found = new dia::Objects (&list);
97+ return *_found;
98+}
99+ //! objects are kept in an ordered list, this is the index of the given object
100+int
101+dia::Layer::object_index (Object* o) const
102+{
103+ g_return_val_if_fail (self != NULL, -1);
104+ return layer_object_index (self, o->Self());
105+}
106+
107+int
108+dia::Layers::len () const
109+{
110+ if (list)
111+ return (*list)->len;
112+ return 0;
113+}
114+dia::Layer*
115+dia::Layers::getitem (int n) const
116+{
117+ if (list && n >= 0 && n < (*list)->len)
118+ return new dia::Layer(static_cast<::Layer*>(g_ptr_array_index (*list, n)));
119+ return 0;
120+}
121+
122+/*!
123+ * DiagramData is the low level Diagram, i.e. everything without an UI
124+ */
125+dia::DiagramData::DiagramData () : self(0), active_layer(0), _selected(0)
126+{
127+ // the usual GObjetc cast DIA_DIAGRAM_DATA does not work when playing games with namespaces ;)
128+ self = static_cast<::DiagramData*> (g_object_new (DIA_TYPE_DIAGRAM_DATA, NULL));
129+ //FIXME: grumpf
130+ if (self->active_layer)
131+ active_layer = new Layer(self->active_layer);
132+ else if (self->layers->len > 0)
133+ active_layer = new Layer((::Layer*)g_ptr_array_index(self->layers, 0));
134+ layers = new Layers(&self->layers);
135+}
136+dia::DiagramData::~DiagramData ()
137+{
138+ g_object_unref (self);
139+ if (_selected)
140+ delete _selected;
141+ if (layers)
142+ delete const_cast<dia::Layers*>(layers);
143+}
144+
145+dia::Layer*
146+dia::DiagramData::add_layer (const char* name)
147+{
148+ int pos = -1; //TODO: make this a parameter
149+ g_return_val_if_fail (self != NULL, 0);
150+ ::Layer* layer = new_layer(g_strdup(name),self);
151+ if (pos != -1)
152+ data_add_layer_at(self, layer, pos);
153+ else
154+ data_add_layer(self, layer);
155+
156+ dia::Layer* dl = new dia::Layer (layer);
157+ return dl;
158+}
159+void
160+dia::DiagramData::update_extents ()
161+{
162+ g_return_if_fail(self != NULL);
163+ data_update_extents(self);
164+ // conceptionally const, i.e. read-only
165+ *const_cast<::Rectangle*>(&extents) = self->extents;
166+}
167+dia::Objects&
168+dia::DiagramData::get_sorted_selected () const
169+{
170+ if (_selected)
171+ delete _selected;
172+
173+ static GList* list = data_get_sorted_selected(self);
174+ const_cast<DiagramData*>(this)->_selected = new dia::Objects (&list);
175+ return *_selected;
176+}
--- /dev/null
+++ b/bindings/dia-diagramdata.h
@@ -0,0 +1,127 @@
1+/*
2+ * C++ interface of DiagramData - just to have something clean to wrap
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__DIAGRAMDATA_H
7+#define DIA__DIAGRAMDATA_H
8+
9+#include "dia-object.h"
10+
11+//! every wrapping object is in the 'dia' namespace
12+//! the C-Objects are only namespaced in the binding
13+namespace dia {
14+
15+class Object;
16+
17+/*!
18+ * \brief A collection of objects
19+ *
20+ * Maybe this should be turned into a template class cause it would need different owners
21+ * depending on its use. The strongest connection is between Object and Layer but there
22+ * are other collections of of Objects like DiagramData::selected or even Group
23+ */
24+class Objects
25+{
26+public :
27+ //! dont use
28+ Objects () : list(0) {}
29+
30+ //! construct from Object owning objects list
31+ Objects (GList** o) : list(o) {}
32+
33+ /* array access */
34+ //! how many contained
35+ int len () const;
36+ //! return back a single one
37+ Object* getitem (int) const;
38+private :
39+ GList** list;
40+};
41+
42+/*!
43+ * \brief Proxy to the Layer object
44+ *
45+ * A Layer is the connection between DiagramData and Object.
46+ * DiagramData has Layers and a Layer has Objects.
47+ */
48+class Layer
49+{
50+public :
51+ //! construct from underlying type: can not be created stand-alone yet.
52+ explicit Layer (::Layer* layer);
53+ //! destroy caches etc.
54+ ~Layer ();
55+ //! the underlying type - only for implementation, not visible in th elanguage binding
56+ ::Layer* Self () const { return self; }
57+ //! collection of contained Object, read-only!
58+ const Objects* objects;
59+ //! add an object to our collection
60+ void add_object (Object* o);
61+ //! recalculation of every Object size and position to update the Layer extents
62+ void update_extents ();
63+ //! the object next to given point but within maxdist
64+ Object* find_closest_object (::Point* pos, double maxdist) const;
65+ //! a list of Object in the given rectangle
66+ Objects& find_objects_in_rectangle (::Rectangle* rect) const;
67+ //! objects are kept in an ordered list, this is the index of the given object
68+ int object_index (Object* o) const;
69+
70+ //! again I would like easy accessor mapping in SWIG
71+ const char* name;
72+private :
73+ ::Layer* self;
74+ Objects* _found; //< backing store for find_objects_in_rectangle
75+};
76+
77+//! \brief container for layer, needed du to msvc6 lacking partial specialization
78+class Layers
79+{
80+public :
81+ //! dont use
82+ Layers () : list(0) {}
83+ //! construct from Dia's container
84+ Layers (GPtrArray** os) : list(os) {}
85+ /* array access */
86+ //! how many contained
87+ int len () const;
88+ //! return back a single one
89+ Layer* getitem (int) const;
90+private :
91+ GPtrArray** list;
92+};
93+
94+/*!
95+ * \brief DiagramData is the low level Diagram, i.e. everything without an UI
96+ *
97+ * The base class for Diagram. The top-level object for libdia containing
98+ * all the other diagram objects.
99+ */
100+class DiagramData
101+{
102+public :
103+ //! the size of the diagram, from last DiagramData::update_extents();
104+ const ::Rectangle extents;
105+ //! trying ot be compatible, read-only
106+ const Layer* active_layer;
107+ //! the read-only list of layers, \todo typemap it in SWIG
108+ const Layers* layers;
109+ //! can be created as stand-alone object
110+ DiagramData ();
111+ //! done with it
112+ ~DiagramData ();
113+ //! get the underlying representation
114+ ::DiagramData* Self () const { return self; }
115+ //! factory function for Layer. They can't stand alone. TODO: decide if this should change the active_layer
116+ Layer* add_layer (const char* name);
117+ //! recalculation of every object to update the diagram extents
118+ void update_extents ();
119+ //! the currently selected objects
120+ Objects& get_sorted_selected () const;
121+private :
122+ ::DiagramData* self;
123+ Objects* _selected; //!< backing store for get_sorted_selected
124+};
125+
126+} // namespace dia
127+#endif /* DIA__DIAGRAMDATA_H */
--- /dev/null
+++ b/bindings/dia-extra.cpp
@@ -0,0 +1,88 @@
1+/*
2+ * C++ implementation of Dia Bindings Helper Functions
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+#include "dia-extra.h"
21+
22+#include <glib.h>
23+#include "message.h"
24+#include "utils.h"
25+
26+#include <stdlib.h>
27+#include <stdio.h>
28+#include <string.h>
29+
30+#include <glib-object.h>
31+#include "properties.h"
32+#include "object.h"
33+#include "plug-ins.h"
34+
35+/*
36+ * copied from ../app/diaconv.c
37+ */
38+static void __cdecl
39+stderr_message_internal(const char *title, const char *fmt,
40+ va_list *args, va_list *args2)
41+{
42+ static gchar *buf = NULL;
43+ static gint alloc = 0;
44+ gint len;
45+
46+ len = format_string_length_upper_bound (fmt, args);
47+
48+ if (len >= alloc) {
49+ if (buf)
50+ g_free (buf);
51+
52+ alloc = nearest_pow (MAX(len + 1, 1024));
53+
54+ buf = g_new (char, alloc);
55+ }
56+
57+ vsprintf (buf, fmt, *args2);
58+
59+ fprintf(stderr,
60+ "%s %s: %s\n",
61+ "",title,buf);
62+}
63+
64+static void
65+dia_extra_redirect (void)
66+{
67+ set_message_func(&stderr_message_internal);
68+}
69+
70+/*!
71+ *
72+ *
73+ * \todo Dia's init function needs to be cleaned. E.g. it would be useful
74+ * to just initialize the plug-ins needed and not everything. Also this
75+ * function may be split to be partially called at bindings initialization
76+ * time.
77+ */
78+void dia::register_plugins ()
79+{
80+ g_type_init();
81+ dia_extra_redirect();
82+ printf ("ATTENTION: crashing may be caused by the other pydia extension picked up here.");
83+ //FIXME: Dia's init functions need to be cleaned - and made aware of multiple calls ...
84+ stdprops_init();
85+
86+ object_registry_init();
87+ dia_register_plugins ();
88+}
--- /dev/null
+++ b/bindings/dia-extra.h
@@ -0,0 +1,11 @@
1+/*
2+ * C++ implementation of Dia Bindings Helper Functions
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+
7+
8+namespace dia {
9+ //! register plug-ins, beware of double bindings
10+ void register_plugins (void);
11+}
--- /dev/null
+++ b/bindings/dia-object.cpp
@@ -0,0 +1,208 @@
1+/*
2+ * C++ interface of DiaObject - just to have something clean to wrap
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+#include "object.h"
21+#include <assert.h>
22+
23+#include "dia-object.h"
24+
25+dia::ObjectType::ObjectType (DiaObjectType* ot) : self(ot), version(ot ? ot->version : -1)
26+{
27+ assert (self);
28+ // read-only which also wont change
29+ name = self->name;
30+}
31+/*! Factory function to create Object of a given type.
32+ *
33+ * \return not only the new Object* but also two 'appropriate' Handle to e.g. connect
34+ * to some other Object
35+ */
36+dia::Object*
37+dia::ObjectType::create(double x, double y, dia::Handle** h1, dia::Handle** h2) const
38+{
39+ ::_Handle *_h1, *_h2;
40+ dia::Object* o;
41+ Point p = {x, y};
42+ void* user_data = 0; //TODO: as parameter ???
43+ if (!self)
44+ return 0;
45+ o = new dia::Object (self->ops->create(&p, user_data ? user_data : self->default_user_data, &_h1, &_h2));
46+ if (h1) *h1 = new dia::Handle (_h1, o->Self());
47+ if (h2) *h2 = new dia::Handle (_h2, o->Self());
48+ return o;
49+}
50+/*!
51+ * Allows to load an object from storage. Not sure if this becomes useful for language bindings.
52+ */
53+dia::Object*
54+dia::ObjectType::load (ObjectNode node, int version, const char* filename) const
55+{
56+ assert (self);
57+ return new dia::Object (self->ops->load (node, version, filename));
58+}
59+/*! Allows to save an Object to ObjectNode file filename.
60+ * . Not sure if this becomes useful for language bindings.
61+ */
62+void
63+dia::ObjectType::save (Object* o, ObjectNode node, const char* filename) const
64+{
65+ assert (self);
66+ self->ops->save (o->Self(), node, filename);
67+}
68+//! OPTIONAL: opens the defaults dialog
69+GtkWidget*
70+dia::ObjectType::get_defaults () const
71+{
72+ assert (self);
73+ if (!self->ops->get_defaults)
74+ return 0;
75+ return self->ops->get_defaults ();
76+}
77+//! OPTIONAL: apply changed defaults
78+void
79+dia::ObjectType::apply_defaults ()
80+{
81+ assert (self);
82+ self->ops->apply_defaults ();
83+}
84+
85+//! create an object wrapper - object previously registered from a plug-in
86+dia::Object::Object (DiaObject* o) : self(o), properties(o), connections(o), handles(o), type(o->type)
87+{
88+}
89+//! destroy the right thing - usually not the underlying object
90+dia::Object::~Object ()
91+{
92+}
93+//! accessor to deliver the objects bounding box
94+::_Rectangle*
95+dia::Object::bbox () const
96+{
97+ return &self->bounding_box;
98+}
99+//! real destruction
100+void
101+dia::Object::destroy ()
102+{
103+ assert (self);
104+ self->ops->destroy (self);
105+}
106+//! drawing the object on the renderer
107+void
108+dia::Object::draw (Renderer* r) const
109+{
110+ assert (self);
111+#if 0 //FIXME: need to think about delegation
112+ self->ops->draw (self, r);
113+#endif
114+}
115+//! calculate the distance betwenn the object and the point
116+double
117+dia::Object::distance_from (Point* p) const
118+{
119+ assert (self);
120+ return self->ops->distance_from (self, p);
121+}
122+//! react on selection (e.g. may change the drawing state)
123+void
124+dia::Object::select (Point* clicked_point, DiaRenderer* interactive_renderer)
125+{
126+ assert (self);
127+ self->ops->selectf (self, clicked_point, interactive_renderer);
128+}
129+//! create a deep copy
130+dia::Object* dia::Object::copy () const
131+{
132+ assert (self);
133+ return new dia::Object (self->ops->copy (self));
134+}
135+//! change position of the whole object
136+ObjectChange*
137+dia::Object::move (double x, double y)
138+{
139+ assert (self);
140+ Point p = {x, y};
141+ return self->ops->move (self, &p);
142+}
143+//! change position of an object handle - this is usually a resize (Attention: does *not* match the C prototype)
144+ObjectChange*
145+dia::Object::move_handle (dia::Handle* h, double x, double y, HandleMoveReason reason, ModifierKeys modifiers)
146+{
147+ assert (self);
148+ Point p = {x, y};
149+ return self->ops->move_handle (self, h->Self(), &p, NULL, reason, modifiers);
150+}
151+//! OPTIONAL: provide a property dialog to change the object proeprties
152+GtkWidget*
153+dia::Object::get_properties (bool is_default) const
154+{
155+ assert (self);
156+ return self->ops->get_properties (self, is_default);
157+}
158+//! OPTIONAL: apply the properties changed in the dialog
159+ObjectChange*
160+dia::Object::apply_properties (GtkWidget* w)
161+{
162+ assert (self);
163+ return self->ops->apply_properties (self, w);
164+}
165+//! OPTIONAL: provide a context menu to change the object states
166+DiaMenu*
167+dia::Object::get_object_menu (Point* pos) const
168+{
169+ assert (self);
170+ return self->ops->get_object_menu (self, pos);
171+}
172+
173+//! StdProps: descibe properties accessible via standard properties API
174+const PropDescription*
175+dia::Object::describe_props () const
176+{
177+ assert (self);
178+ return self->ops->describe_props (self);
179+}
180+//! StdProps: return a list of properties describing the object state
181+void
182+dia::Object::get_props (GPtrArray *props) const
183+{
184+ assert (self);
185+ self->ops->get_props (self, props);
186+}
187+//! StdProps: apply a list of object properties to change the objects state
188+void
189+dia::Object::set_props (GPtrArray *props)
190+{
191+ assert (self);
192+ self->ops->set_props (self, props);
193+}
194+
195+/*!
196+ * \brief factory function for ObjectType (Object factories)
197+ *
198+ * Before this function can return anything useful the ObjectType registry needs to be filled,
199+ * e.g. by dia::register_plugins()
200+ */
201+dia::ObjectType*
202+dia::get_object_type (const char* name)
203+{
204+ ::DiaObjectType* ot = object_get_type(const_cast<char*>(name));
205+ if (ot)
206+ return new dia::ObjectType (ot);
207+ return 0;
208+}
--- /dev/null
+++ b/bindings/dia-object.h
@@ -0,0 +1,111 @@
1+/*
2+ * C++ interface of DiaObject - just to have something clean to wrap
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__OBJECT_H
7+#define DIA__OBJECT_H
8+
9+#include "dia-properties.h"
10+#include "dia-connections.h"
11+
12+namespace dia {
13+
14+//! forward declare
15+class Object;
16+class Renderer;
17+
18+/*!
19+ * \brief ObjectType is the factoy to create Object
20+ *
21+ * To get on all registered ObjectType use dia::registered_types() to create one specific Object
22+ * factory use dia::get_object_type()
23+ */
24+class ObjectType
25+{
26+public :
27+ //! one-time initialized read-only
28+ const char* name;
29+ //! instead of doing this I'd like better accessor support in SWIG
30+ const int version;
31+
32+ //! construct from underlying type
33+ ObjectType (::DiaObjectType* ot);
34+ //! create a default initialized object
35+ Object* create (double x, double y, dia::Handle** h1 = 0, dia::Handle** h2 = 0) const;
36+ //! load an object from storage
37+ Object* load (ObjectNode node, int version, const char* filename) const;
38+ //! save an object to file filename
39+ void save (Object* o, ObjectNode node, const char* filename) const;
40+ //! OPTIONAL: open the defaults dialog
41+ GtkWidget* get_defaults () const;
42+ //! OPTIONAL: apply changed defaults
43+ void apply_defaults ();
44+private :
45+ ::DiaObjectType* self;
46+};
47+
48+/*!
49+ * \brief The basic building block of diagrams
50+ *
51+ * This is a proxy class to objects coming from Dia's object factory. The latter is populate by all the objecct
52+ * implementations from objects/*
53+ */
54+class Object
55+{
56+public :
57+ //! trying to be compatible
58+ const Properties properties;
59+ //! access to this objects connection points
60+ const Connections connections;
61+ //! access to this objects Handles
62+ const Handles handles;
63+ //! the wrapped type (factory)
64+ const ObjectType type;
65+
66+ //! direct property access
67+ ::_Rectangle* bbox () const;
68+
69+ //! create an object wrapper - object previously registered from a plug-in
70+ Object (DiaObject*);
71+ //! destroying the proxy, not the underlying object
72+ ~Object ();
73+ //! not to be wrapped - just used internally
74+ DiaObject* Self() const { return self; }
75+ //! real destruction
76+ void destroy ();
77+ //! drawing the object on the renderer
78+ void draw (Renderer* r) const;
79+ //! calculate the distance betwenn the object and the point
80+ double distance_from (Point* p) const;
81+ //! react on selection (e.g. may change the drawing state)
82+ void select (Point* clicked_point, DiaRenderer* interactive_renderer);
83+ //! create a deep copy
84+ Object* copy () const;
85+ //! change position of the whole object
86+ ObjectChange* move (double x, double y);
87+ //! change position of an object handle - this is usually a resize (Attention: does *not* match the C prototype)
88+ ObjectChange* move_handle (Handle* h, double x, double y, HandleMoveReason reason, ModifierKeys modifiers);
89+
90+ //! OPTIONAL: provide a property dialog to change the object proeprties
91+ GtkWidget* get_properties (bool is_default) const;
92+ //! OPTIONAL: apply the properties changed in the dialog
93+ ObjectChange* apply_properties (GtkWidget*);
94+ //! OPTIONAL: provide a context menu to change the object states
95+ DiaMenu* get_object_menu (Point* pos) const;
96+
97+ //! StdProps: descibe properties accessible via standard properties API
98+ const PropDescription* describe_props () const;
99+ //! StdProps: return a list of properties describing the object state
100+ void get_props (GPtrArray *props) const;
101+ //! StdProps: apply a list of object properties to change the objects state
102+ void set_props (GPtrArray *props);
103+private :
104+ DiaObject* self;
105+};
106+
107+//! factory function to get on the ObjectType
108+ObjectType* get_object_type (const char* name);
109+
110+} // namespace dia
111+#endif /* DIA__OBJECT_H */
--- /dev/null
+++ b/bindings/dia-properties.cpp
@@ -0,0 +1,525 @@
1+/*
2+ * C++ implementation of Dia Properties - just to have something clean to wrap
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+#include "properties.h"
21+// need access to property internals
22+#include "prop_inttypes.h"
23+#include "prop_geomtypes.h"
24+#include "prop_attr.h"
25+#include "prop_text.h"
26+#include "prop_sdarray.h"
27+
28+#include "object.h"
29+#include <assert.h>
30+#include <string>
31+
32+#include "dia-properties.h"
33+#include "dia-object.h"
34+
35+dia::Property<::Property*>::Property (::Property* p) : self(p)
36+{
37+}
38+
39+//! read-only attribute; the name of the property; at least unique within an object, but supposed to be unique global
40+const char*
41+dia::Property<::Property*>::get_name () const
42+{
43+ if (self)
44+ return self->name;
45+ return "<null>::name";
46+}
47+//! read-only attribute giving the data type represented
48+const char*
49+dia::Property<::Property*>::get_type () const
50+{
51+ if (self)
52+ return self->type;
53+ return "<null>::type";
54+}
55+/*!
56+ * \brief getter depending on the type of the property
57+ *
58+ * This is supposed to deliver very different types - which is not possible in a strongly type language.
59+ * We could either have various accessors like:
60+ * template<class T> bool Property::get_value<T>(T*);
61+ * an wrap them into one Property.value for runtime typed languages or ... ?
62+ */
63+bool
64+dia::Property<::Property*>::get (int* v) const
65+{
66+ g_return_val_if_fail (self != NULL, false);
67+ bool ret = true;
68+
69+ if (strcmp (self->type, PROP_TYPE_BOOL) == 0)
70+ *v = ((BoolProperty *)self)->bool_data;
71+ else if (strcmp (self->type, PROP_TYPE_INT) == 0)
72+ *v = ((IntProperty *)self)->int_data;
73+ else if (strcmp (self->type, PROP_TYPE_ENUM) == 0)
74+ *v = ((EnumProperty *)self)->enum_data;
75+ else
76+ ret = false;
77+
78+ return ret;
79+}
80+//! getter for double
81+bool
82+dia::Property<::Property*>::get (double* v) const
83+{
84+ g_return_val_if_fail (self != NULL, false);
85+ if (strcmp (self->type, PROP_TYPE_REAL) == 0) {
86+ *v = ((RealProperty *)self)->real_data;
87+ return true;
88+ }
89+ return false;
90+}
91+//! getter for string
92+bool
93+dia::Property<::Property*>::get (const char** v) const
94+{
95+ g_return_val_if_fail (self != NULL, false);
96+ if (strcmp (self->type, PROP_TYPE_STRING) == 0) {
97+ *v = ((StringProperty*)self)->string_data;
98+ if (*v == NULL)
99+ *v = "";
100+ return true;
101+ }
102+ return false;
103+}
104+//! Now it starts to become ugly: isn't there a better way with SWIG to map one to may types?
105+bool
106+dia::Property<::Property*>::get (::_Point* v) const
107+{
108+ g_return_val_if_fail (self != NULL, false);
109+ if (strcmp (self->type, PROP_TYPE_POINT) == 0) {
110+ *v = ((PointProperty *)self)->point_data;
111+ return true;
112+ }
113+ return false;
114+}
115+//! almost complete ;)
116+bool
117+dia::Property<::Property*>::get (::_Rectangle* v) const
118+{
119+ g_return_val_if_fail (self != NULL, false);
120+ if (strcmp (self->type, PROP_TYPE_RECT) == 0) {
121+ *v = ((RectProperty *)self)->rect_data;
122+ return true;
123+ }
124+ return false;
125+}
126+//! the final one
127+bool
128+dia::Property<::Property*>::get (const std::vector<IProperty*>** v) const
129+{
130+ g_return_val_if_fail (self != NULL, false);
131+ if (strcmp (self->type, PROP_TYPE_DARRAY) == 0) {
132+ // remove everything from an earlier call
133+ std::vector<IProperty*>::iterator it;
134+ // remove const from our cache
135+ std::vector<IProperty*>& vec = const_cast< std::vector<IProperty*>& >(_vec);
136+ for (it = vec.begin(); it != vec.end(); ++it)
137+ delete *it;
138+ vec.clear();
139+
140+ ::ArrayProperty *prop = (::ArrayProperty *)self;
141+
142+ // now build with new values
143+ int num_props = num_props = prop->ex_props->len;
144+ for (int i = 0; i < prop->records->len; ++i) {
145+ ::Property* p = 0;
146+ vec.push_back (new dia::Property <Property*> (0));
147+ }
148+ *v = &vec;
149+ return true;
150+ }
151+ return false;
152+}
153+dia::Property<::Property*>::~Property ()
154+{
155+ std::vector<IProperty*>::iterator it;
156+ for (it = _vec.begin(); it != _vec.end(); ++it)
157+ delete *it;
158+}
159+
160+/*!
161+ * If there is still a property conversion missing it needs to be added
162+ * in four places. In the implmentation dia-properties.cpp, in the
163+ * interface of this class and IProperty: dia-properties.h and finally
164+ * in the .swig file.
165+ */
166+bool
167+dia::Property<::Property*>::get (::_Color* v) const
168+{
169+ g_return_val_if_fail (self != NULL, false);
170+ if (strcmp (self->type, PROP_TYPE_COLOUR) == 0) {
171+ *v = ((ColorProperty *)self)->color_data;
172+ return true;
173+ }
174+ return false;
175+}
176+
177+//! if the property is to be shown (in a dialog)
178+bool
179+dia::Property<::Property*>::visible () const
180+{
181+ g_return_val_if_fail (self != NULL, false);
182+ return !!(self->descr->flags & PROP_FLAG_VISIBLE);
183+}
184+
185+dia::Properties::Properties (::DiaObject* o) : object(o)
186+{
187+}
188+dia::Properties::~Properties ()
189+{
190+}
191+
192+//! is there a property of this name
193+bool
194+dia::Properties::has_key (const char* name) const
195+{
196+ g_return_val_if_fail (object != NULL, false);
197+ if (!object->ops->get_props)
198+ return false;
199+ ::Property *p = object_prop_by_name (object, name);
200+ bool ret = (p != NULL);
201+ if (p)
202+ p->ops->free(p);
203+ return ret;
204+}
205+static bool
206+set_prop (::Property* p, int v)
207+{
208+ if (strcmp (p->type, PROP_TYPE_BOOL) == 0)
209+ ((BoolProperty *)p)->bool_data = (v != 0);
210+ else if (strcmp (p->type, PROP_TYPE_INT) == 0)
211+ ((IntProperty *)p)->int_data = v;
212+ else if (strcmp (p->type, PROP_TYPE_ENUM) == 0)
213+ ((EnumProperty *)p)->enum_data = v;
214+ else
215+ return false;
216+ return true;
217+}
218+static bool
219+set_prop (::Property* p, double v)
220+{
221+ if (strcmp (p->type, PROP_TYPE_REAL) == 0)
222+ ((RealProperty *)p)->real_data = v;
223+ else
224+ return false;
225+ return true;
226+}
227+static bool
228+set_prop (::Property* p, const char* v)
229+{
230+ if (strcmp (p->type, PROP_TYPE_COLOUR) == 0) {
231+ PangoColor color;
232+ if (pango_color_parse(&color, v)) {
233+ ((ColorProperty*)p)->color_data.red = color.red / 65535.0;
234+ ((ColorProperty*)p)->color_data.green = color.green / 65535.0;
235+ ((ColorProperty*)p)->color_data.blue = color.blue / 65535.0;
236+ }
237+ }
238+ else if (strcmp (p->type, PROP_TYPE_STRING) == 0) {
239+ g_free (((StringProperty*)p)->string_data);
240+ ((StringProperty*)p)->string_data = v ? g_strdup (v) : g_strdup ("");
241+ ((StringProperty*)p)->num_lines = 1;
242+ }
243+ else if (strcmp (p->type, PROP_TYPE_TEXT) == 0) {
244+ g_free (((TextProperty*)p)->text_data);
245+ ((TextProperty*)p)->text_data = v ? g_strdup (v) : g_strdup ("");
246+ /* XXX: update size calculation ? */
247+ }
248+ else
249+ return false;
250+ return true;
251+}
252+static bool
253+set_prop (::Property* p, char* v)
254+{
255+ return set_prop (p, (const char*)v);
256+}
257+
258+static bool
259+set_prop (GPtrArray* to, ::ArrayProperty* kinds, int num, const std::vector<dia::IProperty*>&v)
260+{
261+ for (int i = 0; i < v.size() && i < num; ++i) {
262+ ::Property *ex = (::Property*)g_ptr_array_index(kinds->ex_props, i);
263+ ::Property* inner = ex->ops->copy(ex);
264+ dia::IProperty *from = v[i];
265+ int vi;
266+ double vd;
267+ const char* vcs;
268+ char* vs;
269+ const std::vector<dia::IProperty*>* vv;
270+
271+ if (!from)
272+ /* nothing to do, alread initialized */;
273+ else if (from->get (&vi))
274+ set_prop (inner, vi);
275+ else if (from->get (&vd))
276+ set_prop (inner, vi);
277+ else if (from->get (&vcs))
278+ set_prop (inner, vcs);
279+ else if (from->get (&vs))
280+ set_prop (inner, vs);
281+ else if (from->get (&vv)) {
282+ ArrayProperty* ap = (ArrayProperty*)inner;
283+ GPtrArray* record = g_ptr_array_new ();
284+ if (!ap->ex_props) { //FIXME: bug in bindings?
285+ // not sure if this is the right thing to do, reusing kinds
286+ if (!set_prop (to, kinds, vv->size(), *vv))
287+ {
288+ g_warning ("Type mismatch vector<>[%d] '%s'", vv->size(), ap->common.name);
289+ g_ptr_array_free (record, TRUE);
290+ return false;
291+ }
292+ return true;
293+ } else {
294+ set_prop (record, ap, ap->ex_props->len, *vv);
295+ g_ptr_array_add(ap->records, record);
296+ }
297+ }
298+ g_ptr_array_add(to, inner);
299+ }
300+ return true;
301+}
302+//! add a property of type int
303+int
304+dia::Properties::setitem (const char* s, int n)
305+{
306+ g_return_val_if_fail (object != NULL, -1);
307+ ::Property *p = object_prop_by_name (object, s);
308+ if (p) {
309+ bool apply = true;
310+ if (!set_prop (p, n))
311+ printf ("dia::Properties::setitem (%s, %d) type mismatch (%s)\n", s, n, p->type), apply = false;
312+ if (apply) {
313+ GPtrArray *plist = prop_list_from_single (p);
314+ object->ops->set_props(object, plist);
315+ prop_list_free (plist);
316+ }
317+ return 0;
318+ }
319+ printf ("dia::Properties::setitem (%s, %d) none such\n", s, n);
320+ return -1;
321+}
322+//! add a property of type double
323+int
324+dia::Properties::setitem (const char* s, double n)
325+{
326+ g_return_val_if_fail (object != NULL, -1);
327+ ::Property *p = object_prop_by_name (object, s);
328+ if (p) {
329+ bool apply = true;
330+ if (!set_prop (p, n))
331+ printf ("dia::Properties::setitem (%s, %f) type mismatch (%s)\n", s, n, p->type), apply = false;
332+ if (apply) {
333+ GPtrArray *plist = prop_list_from_single (p);
334+ object->ops->set_props(object, plist);
335+ prop_list_free (plist);
336+ }
337+ return 0;
338+ }
339+ printf ("dia::Properties::setitem (%s, %f) none such\n", s, n);
340+ return -1;
341+}
342+//! add a property of type string
343+int
344+dia::Properties::setitem (const char* s, const char* v)
345+{
346+ g_return_val_if_fail (object != NULL, -1);
347+ //printf ("0x%08X->properties['%s'] = '%s'\n", object, s, v);
348+ ::Property *p = object_prop_by_name (object, s);
349+ if (p) {
350+ bool apply = true;
351+ if (!set_prop (p, v))
352+ printf ("dia::Properties::setitem (%s, %s) type mismatch (%s)\n", s, v, p->type), apply = false;
353+
354+ if (apply) {
355+ GPtrArray *plist = prop_list_from_single (p);
356+ object->ops->set_props(object, plist);
357+ prop_list_free (plist);
358+ }
359+ return 0;
360+ }
361+ printf ("dia::Properties::setitem (%s, %s) none such\n", s, v);
362+ return -1;
363+}
364+//! add a property of type double list
365+int
366+dia::Properties::setitem (const char* s, const std::vector<double>& v)
367+{
368+ g_return_val_if_fail (object != NULL, -1);
369+ ::Property *p = object_prop_by_name (object, s);
370+ if (p) {
371+ bool apply = true;
372+ if (strcmp (p->type, PROP_TYPE_COLOUR) == 0 && v.size() == 3) {
373+ ((ColorProperty*)p)->color_data.red = v[0];
374+ ((ColorProperty*)p)->color_data.green = v[1];
375+ ((ColorProperty*)p)->color_data.blue = v[2];
376+ }
377+ else if (strcmp (p->type, PROP_TYPE_LINESTYLE) == 0 && v.size() == 2) {
378+ ((LinestyleProperty *)p)->style = (::LineStyle)(int)v[0];
379+ ((LinestyleProperty *)p)->dash = v[1];
380+ }
381+ else if (strcmp (p->type, PROP_TYPE_POINT) == 0 && v.size() == 2) {
382+ ((PointProperty *)p)->point_data.x = v[0];
383+ ((PointProperty *)p)->point_data.y = v[1];
384+ }
385+ else if (strcmp (p->type, PROP_TYPE_POINTARRAY) == 0) {
386+ PointarrayProperty *ptp = (PointarrayProperty *)p;
387+ int len = v.size() / 2;
388+ g_array_set_size(ptp->pointarray_data,len);
389+ for (int i = 0; i < len; ++i) {
390+ ::Point pt = {v[(i<<1)], v[(i<<1)+1]};
391+ g_array_index(ptp->pointarray_data,Point,i) = pt;
392+ }
393+ }
394+ else if (strcmp (p->type, PROP_TYPE_BEZPOINTARRAY) == 0) {
395+ BezPointarrayProperty *ptp = (BezPointarrayProperty *)p;
396+ // in the folded list the (variable size!) data is packed. So we need to calculate the real length during unpacking
397+ int i = 0;
398+ g_array_set_size(ptp->bezpointarray_data, v.size() / 3); // worst case
399+ std::vector<double>::const_iterator it;
400+ for (it = v.begin(); it != v.end(); ++it) {
401+ ::BezPoint bpt;
402+ g_return_val_if_fail ((int)(*it) >= ::BezPoint::BEZ_MOVE_TO && (int)(*it) <= ::BezPoint::BEZ_CURVE_TO, -1);
403+ bpt.type = (int)(*it) == ::BezPoint::BEZ_MOVE_TO ? ::BezPoint::BEZ_MOVE_TO :
404+ (int)(*it) == ::BezPoint::BEZ_LINE_TO ? ::BezPoint::BEZ_LINE_TO : ::BezPoint::BEZ_CURVE_TO;
405+ ++it; bpt.p1.x = *it;
406+ ++it; bpt.p1.y = *it;
407+ if (bpt.type == ::BezPoint::BEZ_CURVE_TO) {
408+ ++it; bpt.p2.x = *it;
409+ ++it; bpt.p2.y = *it;
410+ ++it; bpt.p3.x = *it;
411+ ++it; bpt.p3.y = *it;
412+ }
413+ else {
414+ if (0 == i && bpt.type != ::BezPoint::BEZ_MOVE_TO)
415+ g_warning("First bezpoint must be BEZ_MOVE_TO");
416+ if (0 < i && bpt.type != ::BezPoint::BEZ_LINE_TO)
417+ g_warning("Further bezpoint must be BEZ_LINE_TO or BEZ_CURVE_TO");
418+ bpt.p2 = bpt.p3 = bpt.p1; // not strictly needed
419+ }
420+ g_array_index(ptp->bezpointarray_data,BezPoint,i) = bpt;
421+ ++i;
422+ }
423+ g_array_set_size(ptp->bezpointarray_data, i); // worst case
424+ }
425+ else
426+ printf ("dia::Properties::setitem (%s, std::vector<double>) type or size (%d) mismatch (%s)\n",
427+ s, static_cast<int>(v.size()), p->type), apply = false;
428+ if (apply) {
429+ GPtrArray *plist = prop_list_from_single (p);
430+ object->ops->set_props(object, plist);
431+ prop_list_free (plist);
432+ }
433+ return 0;
434+ }
435+ printf ("dia::Properties::setitem (%s, std::vector<double>&) none such\n", s);
436+ return -1;
437+}
438+/*!
439+ * \brief set a list of IProperty* which in itself may have std::vector<dia::IProperty*>
440+ *
441+ */
442+int
443+dia::Properties::setitem (const char* s, const std::vector<dia::IProperty*>& vec)
444+{
445+ g_return_val_if_fail (object != NULL, -1);
446+ ::ArrayProperty *pvec = (ArrayProperty *)object_prop_by_name (object, s);
447+ if (pvec) {
448+ guint i, num_props = pvec->ex_props->len;
449+ // clean the previos records
450+ for (i = 0; i < pvec->records->len; ++i) {
451+ GPtrArray* record = (GPtrArray*)g_ptr_array_index(pvec->records, i);
452+ for (int j = 0; j < num_props; ++j) {
453+ ::Property* inner = (::Property*)g_ptr_array_index(record,j);
454+ inner->ops->free(inner);
455+ }
456+ g_ptr_array_free(record, TRUE);
457+ }
458+ g_ptr_array_set_size(pvec->records, 0);
459+ // and fill with new values
460+ for (i = 0; i < vec.size(); ++i) {
461+ // we can only get lists here, every list gives a record and must match in size
462+ const std::vector<dia::IProperty*>* vv;
463+
464+ if (vec[i]->get (&vv)) {
465+ if (vv->size() != num_props)
466+ g_warning ("dia::Properties::setitem() inner list of wrong size");
467+ GPtrArray *record = g_ptr_array_new();
468+ set_prop (record, pvec, num_props, *vv);
469+ g_ptr_array_add(pvec->records, record);
470+ }
471+ }
472+ GPtrArray *plist = prop_list_from_single ((::Property*)pvec);
473+ object->ops->set_props(object, plist);
474+ prop_list_free (plist);
475+
476+ return true;
477+ }
478+ printf ("dia::Properties::setitem (%s, std::vector<std::IProperty*>&) none such\n", s);
479+ return -1;
480+}
481+/*!
482+ * \brief dictionary lookup for a property given by name
483+ *
484+ * It may be desired to make all these properties directly
485+ * available as attribute, so instead of (Python)
486+ * \code
487+ * w = o.properties["elem_width"].value
488+ * \endcode
489+ * one could write
490+ * \code
491+ * w = o.elem_height
492+ * \endcode
493+ * OTOH this would remove the possibility to do reflection on
494+ * the properties, e.g. asking them for type and name. Also it
495+ * may produce namespace clashes for more common property names
496+ * like 'name'.
497+ */
498+dia::IProperty*
499+dia::Properties::getitem (const char* name) const
500+{
501+ g_return_val_if_fail (object != NULL, 0);
502+ ::Property *p = object_prop_by_name (object, name);
503+ if (p)
504+ return new dia::Property<::Property*>(p);
505+ return 0;
506+}
507+
508+//! give all the keys in this map
509+std::vector<char*>
510+dia::Properties::keys () const
511+{
512+ g_return_val_if_fail (object != NULL, _keys);
513+
514+ if (!_keys.empty())
515+ return _keys;
516+ if (object->ops->describe_props) {
517+ const PropDescription *desc = object->ops->describe_props(object);
518+ for (int i = 0; desc[i].name; i++) {
519+ if ((desc[i].flags & PROP_FLAG_WIDGET_ONLY) == 0)
520+ // conceptionally const, just building our cache
521+ const_cast<Properties*>(this)->_keys.push_back (const_cast<char*>(desc[i].name));
522+ }
523+ }
524+ return _keys;
525+}
--- /dev/null
+++ b/bindings/dia-properties.h
@@ -0,0 +1,225 @@
1+/*
2+ * C++ interface of Dia Properties - just to have something clean to wrap
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__PROPERTIES_H
7+#define DIA__PROPERTIES_H
8+
9+#include <string>
10+#include <vector>
11+
12+#include "properties.h"
13+
14+namespace dia {
15+
16+/*!
17+ * \brief Property is the representation of one attribute of an Object
18+ *
19+ * The abstract interface is needed to build a vector of Property. Real properties
20+ * are implemented as template
21+ */
22+class IProperty
23+{
24+public :
25+ //! to make delete delete the real thing
26+ virtual ~IProperty () {}
27+ //! getter depending on the type of the property
28+ virtual bool get (int*) const { return false; }
29+ //! the concrete implementation must deliver the underlying type
30+ virtual bool get (double*) const { return false; }
31+ //! and return true just for that one
32+ virtual bool get (const char**) const { return false; }
33+ //! \todo this seems to be needed due to SWIG's code generattion?
34+ //! It gives: dia-properties.h(30): Warning(509): Overloaded get(char **) const is shadowed by
35+ //! get(char const **) const at dia-properties.h:28.
36+ //! but without it the setting of UMLClass:attributes and members does not work.
37+ //! so before removing it check 'test.py --doc'
38+ virtual bool get (char**) const { return false; }
39+ //! Now it starts to become ugly: isn't there a better way with SWIG to map one to many types?
40+ virtual bool get (::_Point* p) const { return false; }
41+ //! one more ;)
42+ virtual bool get (::_Rectangle* p) const { return false; }
43+ //! and this one ...
44+ virtual bool get (::_Color* p) const { return false; }
45+
46+ //! we can also handle vector<IProperty*>
47+ virtual bool get (const std::vector<IProperty*>**) const { return false; }
48+
49+ //! read-only attribute; the name of the property; at least unique within an object, but supposed to be unique global
50+ virtual const char* get_name () const = 0;
51+ //! read-only attribute giving the data type represented
52+ virtual const char* get_type () const = 0;
53+ //! if the property is to be shown
54+ virtual bool visible () const = 0;
55+};
56+/*!
57+ * \brief To construct any Property type from its underlying type.
58+ *
59+ * This class is used to construct a more complex property and put it into a container of
60+ * properties without having access to the underlying ::Property type.
61+ */
62+template <class T>
63+class Property : public IProperty
64+{
65+public :
66+ //! construct from underlying data type
67+ Property<T> (T v) : self(v) {}
68+ //! the on get function which returns true,
69+ //! because the underlying type matches
70+ virtual bool get (T* p) const { *p = self; return true; }
71+
72+ //! read-only attribute; the name of the property; at least unique within an object,
73+ //! but supposed to be unique globally
74+ const char* get_name () const { return "<name>"; }
75+ //! read-only attribute giving the data type represented
76+ const char* get_type () const { return "<type>"; }
77+ //! if the property is to be shown
78+ bool visible () const { return false; }
79+private :
80+ T self;
81+};
82+
83+inline bool Property<int>::get (int* p) const
84+{
85+ *p = self; return true;
86+}
87+inline bool Property<double>::get (double* p) const
88+{
89+ *p = self; return true;
90+}
91+inline Property<const char*>::Property (const char* v)
92+{
93+ self = v ? g_strdup (v) : g_strdup("");
94+}
95+inline bool Property<const char*>::get (const char** p) const
96+{
97+ *p = self; return true;
98+}
99+inline Property<char*>::Property (char* v)
100+{
101+ self = v ? g_strdup (v) : g_strdup("");
102+}
103+inline bool Property<char*>::get (char** p) const
104+{
105+ *p = self; return true;
106+}
107+
108+/*!
109+ * \brief specialization for getter; a Property from underlying ::Property
110+ *
111+ * The Dia Property System can handle various kinds of properties from simple int
112+ * over Point and Rectangle up to whole Property lists and trees. This class is
113+ * used to get or read a property from its underlying type.
114+ */
115+template<>
116+class Property<::Property*> : public IProperty
117+{
118+public :
119+ //! construct from underlying object
120+ Property (::Property* p);
121+ //! destroy chache
122+ ~Property ();
123+
124+ //! getter depending on the type of the property
125+ virtual bool get (int*) const;
126+ //! the concrete implementation must deliver the underlying type
127+ virtual bool get (double*) const;
128+ //! and return true just for that one
129+ virtual bool get (const char**) const;
130+ //! just one wrapper too much ;)
131+ virtual bool get (::_Point* p) const;
132+ //! one more ;)
133+ virtual bool get (::_Rectangle* p) const;
134+ //! and this one ...
135+ virtual bool get (::_Color* p) const;
136+ //! we can also handle vector<IProperty*>
137+ virtual bool get (const std::vector<IProperty*>**) const;
138+
139+
140+ //! read-only attribute; the name of the property; at least unique within an object, but supposed to be unique global
141+ const char* get_name () const;
142+ //! read-only attribute giving the data type represented
143+ const char* get_type () const;
144+ //! if the property is to be shown
145+ bool visible () const;
146+private :
147+ ::Property* self;
148+ // this is ugly but otherwise we would have an unbound leak
149+ std::vector<IProperty*> _vec;
150+};
151+/*!
152+ * \brief a list of properties; can contain list again so in fact it can be a tree
153+ *
154+ * Some Object Properties consist of Property lists or even property trees. This is the basic
155+ * building block for these complex properties. See 'UML - Class'::operations for an example.
156+ */
157+template<>
158+class Property< std::vector<IProperty*> > : public IProperty, public std::vector<IProperty*>
159+{
160+public :
161+ //! create an empty list
162+ Property () {}
163+ //! empty our list knd of 'deep delete'
164+ ~Property ()
165+ {
166+ std::vector<IProperty*>::iterator it;
167+
168+ for (it = begin(); it != end(); ++it)
169+ delete *it;
170+ }
171+ //! get us self
172+ virtual bool get (const std::vector<IProperty*>** p) const
173+ {
174+ *p = this;
175+ return true;
176+ }
177+ //! read-only attribute; the name of the property; at least unique within an object, but supposed to be unique global
178+ const char* get_name () const { return ""; }
179+ //! read-only attribute giving the data type represented
180+ const char* get_type () const { return "vector<IProperty*>"; }
181+ //! if the property is to be shown
182+ bool visible () const { return false; }
183+};
184+/*!
185+ * \brief A container for Property, merely a fassade to make a group of properties more accessible
186+ *
187+ * In Python this is mapped to the dictionary type, accessing a specific property is done by
188+ * a key lookup with it's name.
189+ *
190+ * To modify an objects property it is needed to modify it's dictionary. This is due to the fact
191+ * that single properties don't have a connection to a specific object but the property map has.
192+ */
193+class Properties
194+{
195+public :
196+ //! construct with/from owning object
197+ Properties (::DiaObject*);
198+ //! destroy the wrapper
199+ ~Properties ();
200+ /* accessors like Python dictionary */
201+ //! is there a property of this name
202+ bool has_key (const char*) const;
203+
204+ //! add a property of type int
205+ int setitem (const char*, int);
206+ //! add a property of type double
207+ int setitem (const char*, double);
208+ //! add a property of type string
209+ int setitem (const char*, const char*);
210+ //! add a property of type double list
211+ int setitem (const char*, const std::vector<double>&);
212+ //! add a property list - intented as final falback
213+ int setitem (const char* s, const std::vector<IProperty*>& vec);
214+ //! return back a single property
215+ IProperty* getitem (const char*) const;
216+ //! give all the keys in this map
217+ std::vector<char*> keys () const;
218+private :
219+ ::DiaObject* object; //!< the owner of the properties
220+
221+ std::vector<char*> _keys; //!< lazy created
222+};
223+
224+} // namespace dia
225+#endif /* DIA__PROPERTIES_H */
--- /dev/null
+++ b/bindings/dia-python-extra.cpp
@@ -0,0 +1,125 @@
1+/*
2+ * some helper function not to pollute the multilingual dia.swig file
3+ *
4+ * Implementation Note: this file should not deal with Dia's Type's but only with some
5+ * conversions from complex Python types to std::types
6+ *
7+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
8+ *
9+ * This is free software; you can redistribute it and/or modify
10+ * it under the terms of the GNU General Public License as published by
11+ * the Free Software Foundation; either version 2 of the License, or
12+ * (at your option) any later version.
13+ *
14+ * This program is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program; if not, write to the Free Software
21+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22+ */
23+
24+#include <Python.h>
25+#include <assert.h>
26+
27+#include "dia-python-extra.h"
28+
29+/*
30+ * \brief Try to convert a 'nested' Python Object into a flat vector.
31+ *
32+ * With templates not working that well betwenn SWIG and msvc6 here's some manual conversion.
33+ * Basically this is 'unrolling' tuples and lists to a flat std::vector and delegating that
34+ * to the C++ object, which than converts again to the concrete properties type.
35+ * As a short-cut int is converted to double if the first or last element is a double.
36+ * Yes I know this code is ugly. Let's see if other language binders do better ;)
37+ */
38+bool
39+DiaPythonExtra_ToVector (PyObject* v, std::vector<double>& vec)
40+{
41+ if ((PyList_Check(v) && PyList_Size(v) > 0) || (PyTuple_Check(v) && PyTuple_Size(v) > 0)) {
42+ bool isList = PyList_Check(v);
43+ int size = isList ? PyList_Size(v) : PyTuple_Size (v);
44+
45+ for (int i = 0; i < size; ++i) {
46+ PyObject *a = isList ? PyList_GetItem(v, i) : PyTuple_GetItem (v, i);
47+ if (PyFloat_Check(a) || PyInt_Check(a))
48+ vec.push_back (PyFloat_Check(a) ? PyFloat_AsDouble(a) : PyInt_AsLong(a));
49+ else if (PyTuple_Check (a)) {
50+ for (int j = 0; j < PyTuple_Size (a); ++j) {
51+ PyObject* b = PyTuple_GetItem (a, j);
52+ if (!PyFloat_Check(b) && !PyInt_Check (b))
53+ return false; // wrong type
54+ vec.push_back (PyFloat_Check(b) ? PyFloat_AsDouble(b) : PyInt_AsLong(b));
55+ }
56+ } else {
57+ return false; // only one level of nesting supported
58+ }
59+ }
60+ return true;
61+ }
62+ return false;
63+}
64+
65+/*!
66+ * \brief recursive function doing the real conversion work for tree<IProperty*>
67+ *
68+ * \return false on no vector input
69+ */
70+static bool
71+_ToVector (PyObject* v, std::vector<dia::IProperty*>& vec)
72+{
73+ bool isList = PyList_Check(v);
74+ bool isTuple = PyTuple_Check(v);
75+
76+ if (isList || isTuple) {
77+ int len = isList ? PyList_Size(v): PyTuple_Size(v);
78+
79+ for (int i = 0; i < len; ++i) {
80+ PyObject *o = isList ? PyList_GetItem(v, i) : PyTuple_GetItem(v, i);
81+ if (PyString_Check (o))
82+ vec.push_back (new dia::Property<char*>(PyString_AsString (o)));
83+ else if (PyUnicode_Check (o))
84+ {
85+ PyObject *uval = PyUnicode_AsUTF8String (o);
86+ vec.push_back (new dia::Property<char*>(PyString_AsString(uval)));
87+ Py_DECREF (uval);
88+ }
89+ else if (PyList_Check(o) || PyTuple_Check(o)) {
90+ // dive into
91+ dia::Property< std::vector<dia::IProperty*> >* inner =
92+ new dia::Property< std::vector<dia::IProperty*> >();
93+ _ToVector (o, *inner);
94+ vec.push_back (inner);
95+ } else if (PyInt_Check(o))
96+ vec.push_back (new dia::Property<int>(PyInt_AsLong (o)));
97+ else if (PyFloat_Check (o))
98+ vec.push_back (new dia::Property<double>(PyFloat_AsDouble (o)));
99+ else if (Py_None == o)
100+ vec.push_back (0);
101+ else
102+ {
103+ PyObject* s = PyObject_Str (o);
104+ printf ("_ToVector() : no conversion for '%s'\n", PyString_AsString (s));
105+ }
106+ }
107+ return true;
108+ }
109+ return false;
110+}
111+
112+/*!
113+ * \brief Generic way to create a property vector/tree
114+ *
115+ * To allow the assignment of complex properties built from native language
116+ * types some binding language specific support is needed.
117+ */
118+bool
119+DiaPythonExtra_ToVector (PyObject* v, std::vector<dia::IProperty*>& vec)
120+{
121+ // we can deal handle empty lists/tuples as well
122+ if (PyList_Check(v) || PyTuple_Check(v))
123+ return _ToVector (v, vec);
124+ return false;
125+}
--- /dev/null
+++ b/bindings/dia-python-extra.h
@@ -0,0 +1,17 @@
1+/*
2+ * some helper function not to pollute the multilingual dia.swig file
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__PYTHON_EXTRA_H
7+#define DIA__PYTHON_EXTRA_H
8+
9+#include <vector>
10+#include <string>
11+
12+#include "dia-properties.h"
13+
14+bool DiaPythonExtra_ToVector (PyObject*, std::vector<double>& vec);
15+bool DiaPythonExtra_ToVector (PyObject*, std::vector<dia::IProperty*>& vec);
16+
17+#endif /* DIA__PYTHON_EXTRA_H */
\ No newline at end of file
--- /dev/null
+++ b/bindings/dia-renderer.cpp
@@ -0,0 +1,283 @@
1+/*
2+ * C++ interface of DiaRenderer - just to have something clean to wrap
3+ *
4+ * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5+ *
6+ * This is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 2 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program; if not, write to the Free Software
18+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+ */
20+
21+#include "diarenderer.h"
22+#include <assert.h>
23+
24+#include "object.h"
25+#include "dia-object.h"
26+
27+#include "dia-renderer.h"
28+
29+// return width in pixels, only for interactive renderers
30+int
31+dia::Renderer::get_width_pixels () const
32+{
33+ assert (self);
34+ return DIA_RENDERER_GET_CLASS(self)->get_width_pixels (self);
35+}
36+// return width in pixels, only for interactive renderers
37+int
38+dia::Renderer::get_height_pixels () const
39+{
40+ assert (self);
41+ return DIA_RENDERER_GET_CLASS(self)->get_height_pixels (self);
42+}
43+// simply calls the objects draw function, which calls this again
44+void
45+dia::Renderer::draw_object (Object* o)
46+{
47+ assert (self);
48+ DIA_RENDERER_GET_CLASS(self)->draw_object (self, o->Self());
49+}
50+// Returns the EXACT width of text in cm, using the current font.
51+double
52+dia::Renderer::get_text_width (const gchar *text, int length) const
53+{
54+ assert (self);
55+ return DIA_RENDERER_GET_CLASS(self)->get_text_width (self, text, length);
56+}
57+// called before any rendering takes palce
58+void
59+dia::Renderer::begin_render ()
60+{
61+ assert (self);
62+ DIA_RENDERER_GET_CLASS(self)->begin_render (self);
63+}
64+// finished rendering
65+void
66+dia::Renderer::end_render ()
67+{
68+ assert (self);
69+ DIA_RENDERER_GET_CLASS(self)->end_render (self);
70+}
71+// set current linewidth
72+void
73+dia::Renderer::set_linewidth (double w)
74+{
75+ assert (self);
76+ DIA_RENDERER_GET_CLASS(self)->set_linewidth (self, w);
77+}
78+// set current linecaps
79+void
80+dia::Renderer::set_linecaps (LineCaps mode)
81+{
82+ assert (self);
83+ DIA_RENDERER_GET_CLASS(self)->set_linecaps (self, mode);
84+}
85+// set current linejoin
86+void
87+dia::Renderer::set_linejoin (LineJoin join)
88+{
89+ assert (self);
90+ DIA_RENDERER_GET_CLASS(self)->set_linejoin (self, join);
91+}
92+// set current linestyle
93+void
94+dia::Renderer::set_linestyle (LineStyle style)
95+{
96+ assert (self);
97+ DIA_RENDERER_GET_CLASS(self)->set_linestyle (self, style);
98+}
99+// set current dashlength
100+void
101+dia::Renderer::set_dashlength (double length)
102+{
103+ assert (self);
104+ DIA_RENDERER_GET_CLASS(self)->set_dashlength (self, length);
105+}
106+// set current font
107+void
108+dia::Renderer::set_font (Font* font, double height)
109+{
110+ assert (self);
111+ //FIXME: implement
112+}
113+// Draw a line from start to end, using color and the current line style
114+void
115+dia::Renderer::draw_line (Point *start, Point *end, Color *color)
116+{
117+ assert (self);
118+ DIA_RENDERER_GET_CLASS(self)->draw_line (self, start, end, color);
119+}
120+// Fill a rectangle, given its upper-left and lower-right corners
121+void
122+dia::Renderer::fill_rect (Point *ul_corner, Point *lr_corner, Color *color)
123+{
124+ assert (self);
125+ DIA_RENDERER_GET_CLASS(self)->fill_rect (self, ul_corner, lr_corner, color);
126+}
127+// the polygon is filled using the current fill type, no border is drawn
128+void
129+dia::Renderer::fill_polygon (Point *points, int num_points, Color *color)
130+{
131+ assert (self);
132+ DIA_RENDERER_GET_CLASS(self)->fill_polygon (self, points, num_points, color);
133+}
134+// Draw an arc, given its center, the bounding box (widget, height), the start angle and the end angle
135+void
136+dia::Renderer::draw_arc (Point *center, double width, double height,
137+ double angle1, double angle2,
138+ Color *color)
139+{
140+ assert (self);
141+ DIA_RENDERER_GET_CLASS(self)->draw_arc (self, center, width, height, angle1, angle2, color);
142+}
143+// Same a DrawArcFunc except the arc is filled (a pie-chart)
144+void
145+dia::Renderer::fill_arc (Point *center, double width, double height,
146+ double angle1, double angle2,
147+ Color *color)
148+{
149+ assert (self);
150+ DIA_RENDERER_GET_CLASS(self)->fill_arc (self, center, width, height, angle1, angle2, color);
151+}
152+// Draw an ellipse, given its center and the bounding box
153+void
154+dia::Renderer::draw_ellipse (Point *center, double width, double height, Color *color)
155+{
156+ assert (self);
157+ DIA_RENDERER_GET_CLASS(self)->draw_ellipse (self, center, width, height, color);
158+}
159+// Same a DrawEllipse, except the ellips is filled
160+void
161+dia::Renderer::fill_ellipse (Point *center, double width, double height, Color *color)
162+{
163+ assert (self);
164+ DIA_RENDERER_GET_CLASS(self)->fill_ellipse (self, center, width, height, color);
165+}
166+// Print a string at pos, using the current font
167+void
168+dia::Renderer::draw_string (const gchar *text, Point *pos, Alignment alignment, Color *color)
169+{
170+ assert (self);
171+ DIA_RENDERER_GET_CLASS(self)->draw_string (self, text, pos, alignment, color);
172+}
173+// Draw an image, given its bounding box
174+void
175+dia::Renderer::draw_image (Point *point, double width, double height, Image* image)
176+{
177+ assert (self);
178+ //FIXME: DIA_RENDERER_GET_CLASS(self)->draw_image (self, point, width, height, image);
179+}
180+
181+// draw a bezier line - possibly as approximation consisting of straight lines
182+void
183+dia::Renderer::draw_bezier (BezPoint *points, int numpoints, Color *color)
184+{
185+ assert (self);
186+ DIA_RENDERER_GET_CLASS(self)->draw_bezier (self, points, numpoints, color);
187+}
188+// fill a bezier line - possibly as approximation consisting of a polygon
189+void
190+dia::Renderer::fill_bezier (BezPoint *points, int numpoints, Color *color)
191+{
192+ assert (self);
193+ DIA_RENDERER_GET_CLASS(self)->fill_bezier (self, points, numpoints, color);
194+}
195+// drawing a polyline - or fallback to single line segments
196+void
197+dia::Renderer::draw_polyline (Point *points, int num_points, Color *color)
198+{
199+ assert (self);
200+ DIA_RENDERER_GET_CLASS(self)->draw_polyline (self, points, num_points, color);
201+}
202+// Draw a polygone, using the current line style
203+void
204+dia::Renderer::draw_polygon (Point *points, int num_points, Color *color)
205+{
206+ assert (self);
207+ DIA_RENDERER_GET_CLASS(self)->draw_polygon (self, points, num_points, color);
208+}
209+// draw a Text. It holds its own information like position, style, ...
210+void
211+dia::Renderer::draw_text (Text* text)
212+{
213+ assert (self);
214+ DIA_RENDERER_GET_CLASS(self)->draw_text (self, text);
215+}
216+// Draw a rectangle, given its upper-left and lower-right corners
217+void
218+dia::Renderer::draw_rect (Point *ul_corner, Point *lr_corner, Color *color)
219+{
220+ assert (self);
221+ DIA_RENDERER_GET_CLASS(self)->draw_rect (self, ul_corner, lr_corner, color);
222+}
223+// a polyline with round coners
224+void
225+dia::Renderer::draw_rounded_polyline (Point *points, int num_points, Color *color, double radius )
226+{
227+ assert (self);
228+ DIA_RENDERER_GET_CLASS(self)->draw_rounded_polyline (self, points, num_points, color, radius);
229+}
230+// specialized draw_rect() with round corners
231+void
232+dia::Renderer::draw_rounded_rect (Point *ul_corner, Point *lr_corner, Color *color, real radius)
233+{
234+ assert (self);
235+ DIA_RENDERER_GET_CLASS(self)->draw_rounded_rect (self, ul_corner, lr_corner, color, radius);
236+}
237+// specialized draw_rect() with round corners
238+void
239+dia::Renderer::fill_rounded_rect (Point *ul_corner, Point *lr_corner, Color *color, real radius)
240+{
241+ assert (self);
242+ DIA_RENDERER_GET_CLASS(self)->fill_rounded_rect (self, ul_corner, lr_corner, color, radius);
243+}
244+// specialized draw_line() for renderers with an own concept of Arrow
245+void
246+dia::Renderer::draw_line_with_arrows (Point *start, Point *end, real line_width, Color *line_color,
247+ Arrow *start_arrow, Arrow *end_arrow)
248+{
249+ assert (self);
250+ DIA_RENDERER_GET_CLASS(self)->draw_line_with_arrows (self, start, end, line_width, line_color, start_arrow, end_arrow);
251+}
252+// specialized draw_line() for renderers with an own concept of Arrow
253+void
254+dia::Renderer::draw_arc_with_arrows (Point *start, Point *end, Point *midpoint, real line_width, Color *color,
255+ Arrow *start_arrow, Arrow *end_arrow)
256+{
257+ assert (self);
258+ DIA_RENDERER_GET_CLASS(self)->draw_arc_with_arrows (self, start, end, midpoint, line_width, color, start_arrow, end_arrow);
259+}
260+// specialized draw_polyline() for renderers with an own concept of Arrow
261+void
262+dia::Renderer::draw_polyline_with_arrows (Point *points, int num_points, real line_width, Color *color,
263+ Arrow *start_arrow, Arrow *end_arrow)
264+{
265+ assert (self);
266+ DIA_RENDERER_GET_CLASS(self)->draw_polyline_with_arrows (self, points, num_points, line_width, color, start_arrow, end_arrow);
267+}
268+// specialized draw_rounded_polyline() for renderers with an own concept of Arrow
269+void
270+dia::Renderer::draw_rounded_polyline_with_arrows (Point *points, int num_points, real line_width, Color *color,
271+ Arrow *start_arrow, Arrow *end_arrow, real radius)
272+{
273+ assert (self);
274+ DIA_RENDERER_GET_CLASS(self)->draw_rounded_polyline_with_arrows (self, points, num_points, line_width, color, start_arrow, end_arrow, radius);
275+}
276+// specialized draw_bezier() for renderers with an own concept of Arrow
277+void
278+dia::Renderer::draw_bezier_with_arrows (BezPoint *points, int num_points, real line_width, Color *color,
279+ Arrow *start_arrow, Arrow *end_arrow)
280+{
281+ assert (self);
282+ DIA_RENDERER_GET_CLASS(self)->draw_bezier_with_arrows (self, points, num_points, line_width, color, start_arrow, end_arrow);
283+}
--- /dev/null
+++ b/bindings/dia-renderer.h
@@ -0,0 +1,170 @@
1+/*
2+ * C++ interface of DiaRenderer - just to have something clean to wrap
3+ *
4+ * Copyright 2007, Hans Breuer, GPL, see COPYING
5+ */
6+#ifndef DIA__RENDERER_H
7+#define DIA__RENDERER_H
8+
9+namespace dia {
10+
11+//! forward declare
12+class Object;
13+class Image;
14+class Font;
15+
16+/*!
17+ * \brief Renderer provides functions to draw Object by their simple geometrics
18+ *
19+ * This class is not very useful until one wants to implement an Object in the target
20+ * language. Than it is needed to abstract away the the real drawing to different
21+ * backends from the drawing code in Object::draw(Renderer*).
22+ * Another use-case may be a unit test where single renderers functions chould be
23+ * tested. For both cases a renderer factory function would be needed.
24+ */
25+class Renderer
26+{
27+public :
28+ /// \defgroup InteractiveRenderer The 'interactive' renderer interface
29+ /// IIRC this functions are only supported by interactive renderers
30+
31+ //! return width in pixels, only for interactive renderers
32+ //! \ingroup InteractiveRenderer
33+ virtual int get_width_pixels () const;
34+ //! return width in pixels, only for interactive renderers
35+ //! \ingroup InteractiveRenderer
36+ virtual int get_height_pixels () const;
37+
38+ /// \defgroup RendererRequired Functions to be implemented by every Renderer
39+ /// Not sure about this ;)
40+
41+ //! simply calls the objects draw function, which calls this again
42+ //! \ingroup RendererRequired
43+ virtual void draw_object (Object*);
44+ //! Returns the EXACT width of text in cm, using the current font.
45+ //! There has been some confusion as to the definition of this.
46+ //! It used to say the width was in pixels, but actual width returned
47+ //! was cm. You shouldn't know about pixels anyway.
48+ //! \ingroup RendererRequired
49+ virtual double get_text_width (const gchar *text, int length) const;
50+
51+ //! called before any rendering takes palce
52+ //! \ingroup RendererRequired
53+ virtual void begin_render ();
54+ //! finished rendering
55+ //! \ingroup RendererRequired
56+ virtual void end_render ();
57+ //! set current line width
58+ //! \ingroup RendererRequired
59+ virtual void set_linewidth (double w);
60+ //! set current ends
61+ //! \ingroup RendererRequired
62+ virtual void set_linecaps (LineCaps mode);
63+ //! set current joining
64+ //! \ingroup RendererRequired
65+ virtual void set_linejoin (LineJoin join);
66+ //! set current line style (dottet, dashed, solid)
67+ //! \ingroup RendererRequired
68+ virtual void set_linestyle (LineStyle style);
69+ //! set current length for dashes
70+ //! \ingroup RendererRequired
71+ virtual void set_dashlength (double length);
72+ //! set current font
73+ //! \ingroup RendererRequired
74+ //! \todo wrap font objecs ?
75+ virtual void set_font (Font* font, double height);
76+ //! Draw a line from start to end, using color and the current line style
77+ //! \ingroup RendererRequired
78+ virtual void draw_line (Point *start, Point *end, Color *color);
79+ //! Fill a rectangle, given its upper-left and lower-right corners
80+ //! \ingroup RendererRequired
81+ virtual void fill_rect (Point *ul_corner, Point *lr_corner, Color *color);
82+ //! the polygon is filled using the current fill type, no border is drawn
83+ //! \ingroup RendererRequired
84+ virtual void fill_polygon (Point *points, int num_points, Color *color);
85+ //! Draw an arc, given its center, the bounding box (widget, height), the start angle and the end angle
86+ //! \ingroup RendererRequired
87+ virtual void draw_arc (Point *center, double width, double height,
88+ double angle1, double angle2,
89+ Color *color);
90+ //! Same a DrawArcFunc except the arc is filled (a pie-chart)
91+ //! \ingroup RendererRequired
92+ virtual void fill_arc (Point *center, double width, double height,
93+ double angle1, double angle2,
94+ Color *color);
95+ //! Draw an ellipse, given its center and the bounding box
96+ //! \ingroup RendererRequired
97+ virtual void draw_ellipse (Point *center, double width, double height, Color *color);
98+ //! Same a DrawEllipse, except the ellips is filled
99+ //! \ingroup RendererRequired
100+ virtual void fill_ellipse (Point *center, double width, double height, Color *color);
101+ //! Print a string at pos, using the current font
102+ //! \ingroup RendererRequired
103+ virtual void draw_string (const gchar *text, Point *pos, Alignment alignment, Color *color);
104+ //! Draw an image, given its bounding box
105+ //! \ingroup RendererRequired
106+ virtual void draw_image (Point *point, double width, double height, Image* image);
107+
108+ /// \defgroup RenderMedium Renderer Should Implemement This
109+ /// Functions which SHOULD be implemented by specific renderer, but
110+ /// have a default implementation based on the above functions
111+
112+ //! draw a bezier line - possibly as approximation consisting of straight lines
113+ //! \ingroup RenderMedium
114+ virtual void draw_bezier (BezPoint *points, int numpoints, Color *color);
115+ //! fill a bezier line - possibly as approximation consisting of a polygon
116+ //! \ingroup RenderMedium
117+ virtual void fill_bezier (BezPoint *points, int numpoints, Color *color);
118+ //! drawing a polyline - or fallback to single line segments
119+ //! \ingroup RenderMedium
120+ virtual void draw_polyline (Point *points, int num_points, Color *color);
121+ //! Draw a polygone, using the current line style
122+ //! \ingroup RenderMedium
123+ virtual void draw_polygon (Point *points, int num_points, Color *color);
124+ //! draw a Text. It holds its own information like position, style, ...
125+ //! \ingroup RenderMedium
126+ virtual void draw_text (Text* text);
127+ //! Draw a rectangle, given its upper-left and lower-right corners
128+ //! \ingroup RenderMedium
129+ virtual void draw_rect (Point *ul_corner, Point *lr_corner, Color *color);
130+
131+ /// \defgroup RenderHigh Renderer Can Implement This
132+ //! Highest level functions, probably only to be implemented by
133+ //! special 'high level' renderers which have a concept of arrows or rounded drawings
134+
135+ //! a polyline with round coners
136+ //! \ingroup RenderHigh
137+ virtual void draw_rounded_polyline (Point *points, int num_points, Color *color, double radius );
138+ //! specialized draw_rect() with round corners
139+ //! \ingroup RenderHigh
140+ virtual void draw_rounded_rect (Point *ul_corner, Point *lr_corner, Color *color, real radius);
141+ //! specialized draw_rect() with round corners
142+ //! \ingroup RenderHigh
143+ virtual void fill_rounded_rect (Point *ul_corner, Point *lr_corner, Color *color, real radius);
144+ //! specialized draw_line() for renderers with an own concept of Arrow
145+ //! \ingroup RenderHigh
146+ virtual void draw_line_with_arrows (Point *start, Point *end, real line_width, Color *line_color,
147+ Arrow *start_arrow, Arrow *end_arrow);
148+ //! specialized draw_line() for renderers with an own concept of Arrow
149+ //! \ingroup RenderHigh
150+ virtual void draw_arc_with_arrows (Point *start, Point *end, Point *midpoint, real line_width, Color *color,
151+ Arrow *start_arrow, Arrow *end_arrow);
152+ //! specialized draw_polyline() for renderers with an own concept of Arrow
153+ //! \ingroup RenderHigh
154+ virtual void draw_polyline_with_arrows (Point *points, int num_points, real line_width, Color *color,
155+ Arrow *start_arrow, Arrow *end_arrow);
156+ //! specialized draw_rounded_polyline() for renderers with an own concept of Arrow
157+ //! \ingroup RenderHigh
158+ virtual void draw_rounded_polyline_with_arrows (Point *points, int num_points, real line_width, Color *color,
159+ Arrow *start_arrow, Arrow *end_arrow, real radius);
160+ //! specialized draw_bezier() for renderers with an own concept of Arrow
161+ //! \ingroup RenderHigh
162+ virtual void draw_bezier_with_arrows (BezPoint *points, int num_points, real line_width, Color *color,
163+ Arrow *start_arrow, Arrow *end_arrow);
164+
165+private :
166+ DiaRenderer* self;
167+};
168+
169+} // namespace dia
170+#endif /* DIA__RENDERER_H */
--- /dev/null
+++ b/bindings/dia.swig
@@ -0,0 +1,369 @@
1+%module dia
2+%{
3+#include "object.h"
4+#include "diarenderer.h"
5+#include "diagramdata.h"
6+#include "filter.h"
7+#include "plug-ins.h"
8+#include "properties.h"
9+
10+// helper functions
11+#ifdef SWIGPYTHON
12+#include "dia-python-extra.h"
13+#endif
14+#include "dia-extra.h"
15+
16+// the wrapper headers
17+#include "dia-properties.h"
18+#include "dia-object.h"
19+#include "dia-renderer.h"
20+#include "dia-diagramdata.h"
21+%}
22+
23+#define G_GNUC_CONST
24+#define G_BEGIN_DECLS
25+#define G_END_DECLS
26+#define G_INLINE_FUNC
27+// for SWIG these are the same types
28+typedef char gchar;
29+
30+%ignore TYPES_H;
31+%include "diatypes.h"
32+
33+// the renaming needs to be done before SWIG sees the declarations
34+%rename(Rectangle) _Rectangle;
35+// this should be merged with rectangle somehow
36+%rename(IntRectangle) _IntRectangle;
37+%rename(Point) _Point;
38+%rename(BezPoint) _BezPoint;
39+
40+%ignore GEOMETRY_H;
41+// and a bunch of other stuff not yet needed
42+%ignore point_add;
43+%ignore point_sub;
44+%ignore point_dot;
45+%ignore point_len;
46+%ignore point_scale;
47+%ignore point_rotate;
48+%ignore point_normalize;
49+%ignore point_get_perp;
50+%ignore point_copy;
51+%ignore point_add_scaled;
52+%ignore point_convex;
53+%ignore point_get_normed;
54+%ignore point_copy_add_scaled;
55+%ignore point_in_rectangle;
56+%ignore rectangle_in_rectangle;
57+%ignore rectangle_union;
58+%ignore int_rectangle_union;
59+%ignore rectangle_intersection;
60+%ignore rectangle_intersects;
61+%ignore rectangle_add_point;
62+%ignore rectangle_equals;
63+%ignore closest_to;
64+%ignore distance_bez_seg_point;
65+%ignore distance_point_point;
66+%ignore distance_point_point_manhattan;
67+%ignore distance_rectangle_point;
68+%ignore distance_line_point;
69+%ignore distance_polygon_point;
70+%ignore distance_bez_line_point;
71+%ignore distance_bez_shape_point;
72+%ignore distance_ellipse_point;
73+%ignore identity_matrix;
74+%ignore mult_matrix;
75+%ignore translate_matrix;
76+%ignore rotate_matrix;
77+%ignore transform_point;
78+%ignore scale_matrix;
79+%ignore xshear_matrix;
80+%ignore yshear_matrix;
81+%ignore dot2;
82+%ignore line_coef;
83+%ignore line_to_point;
84+%ignore point_perp;
85+%ignore fillet;
86+%ignore point_cross;
87+%ignore calculate_object_edge;
88+%include "geometry.h"
89+
90+// again using the original header
91+%nodefaultctor; // Don't create default constructors
92+%rename(ImportFilter) _DiaImportFilter;
93+%rename(ExportFilter) _DiaExportFilter;
94+%rename(CallbackFilter) _DiaCallbackFilter;
95+%immutable; // the following are all read-only
96+%include "filter.h"
97+%clearnodefaultctor; // Re-enable default constructors
98+%mutable;
99+
100+%rename(Color) _Color;
101+// redefinition - the original header 'color.h' is too ugly to parse
102+struct _Color
103+{
104+ float red;
105+ float green;
106+ float blue;
107+};
108+
109+#if 0 /* works for vc7.1, but not with vc6 and *not* for const char* ?
110+ * All the partial specialization needs to be avoided with vc6, no compiler support!
111+ */
112+%include "std_vector.i"
113+using namespace std;
114+namespace std {
115+ %template(vectorString) vector<char*>;
116+}
117+#else
118+# ifdef SWIGPYTHON
119+// after hours of trying starting with 'const std::vector<const char*>&' this one seems to work ...
120+%typemap (out) std::vector<char*> {
121+ int size = $1.size();
122+ $result = PyList_New(size);
123+ for (int i=0; i<size; i++)
124+ PyList_SetItem($result,i,PyString_FromString ($1[i]));
125+}
126+# endif
127+#endif
128+
129+// hide the internal helper of all our wrapper clsses
130+%ignore *::Self;
131+
132+%ignore dia::Property;
133+%rename(Property) dia::IProperty;
134+%include attribute.i
135+%attribute(dia::IProperty, char*, type, get_type);
136+%attribute(dia::IProperty, char*, name, get_name);
137+%nodefaultctor; // Don't create default constructors
138+%include "dia-properties.h"
139+%clearnodefaultctor; // Re-enable default constructors
140+
141+// in general we can't handle any of our objects being NULL
142+%include "constraints.i"
143+%apply Pointer NONNULL { dia::IProperty * };
144+%apply Pointer NONNULL { dia::Object * };
145+%apply Pointer NONNULL { dia::Layer * };
146+%apply Pointer NONNULL { dia::DiagramData * };
147+
148+// this is needed to make iteration via __getitem__ work, i.e. not returning None objects.
149+// It tells SWIG to check every such pointer return and set/do the appropriate error/return.
150+%typemap(ret) dia::Object*, dia::Handle*, dia::ConnectionPoint*, dia::Layer* {
151+ if ($1 == NULL) {
152+ PyErr_SetString (PyExc_IndexError, "not in list");
153+ return NULL;
154+ }
155+}
156+%typemap(ret) dia::IProperty*, dia::ObjectType* {
157+ if ($1 == NULL) {
158+ PyErr_SetString (PyExc_KeyError, "none such");
159+ return NULL;
160+ }
161+}
162+
163+#ifdef SWIGPYTHON
164+%extend dia::IProperty {
165+ %immutable;
166+ PyObject* value;
167+ %mutable;
168+};
169+%inline %{
170+PyObject* dia_IProperty_value_get (dia::IProperty* self) {
171+ int vi;
172+ if (self->get (&vi)) return PyInt_FromLong(vi);
173+ double vd;
174+ if (self->get (&vd)) return PyFloat_FromDouble(vd);
175+ const char* vcs;
176+ if (self->get (&vcs)) return PyString_FromString(vcs);
177+ char* vs; // not sure if this duplication const char* vs. char* is really needed
178+ if (self->get (&vs)) return PyString_FromString(vs);
179+ ::_Point vp;
180+ if (self->get (&vp)) return SWIG_NewPointerObj(&vp, SWIGTYPE_p__Point, 0);
181+ ::_Rectangle vr;
182+ if (self->get (&vr)) return SWIG_NewPointerObj(&vr, SWIGTYPE_p__Rectangle, 0);
183+ ::_Color vc;
184+ if (self->get (&vc)) return SWIG_NewPointerObj(&vc, SWIGTYPE_p__Color, 0);
185+ const std::vector<dia::IProperty*>* vecProp;
186+ if (self->get (&vecProp)) {
187+ const n = vecProp->size();
188+ PyObject* ret = PyTuple_New(n);
189+ for (int i = 0; i < n; ++i)
190+ PyTuple_SetItem(ret, i, SWIG_NewPointerObj((*vecProp)[i], SWIGTYPE_p_dia__IProperty, 0));
191+ return ret;
192+ }
193+
194+ // generic fallback - not of much use if one is interested in value
195+ return SWIG_NewPointerObj(self, SWIGTYPE_p_dia__IProperty, 0);
196+}
197+%}
198+#endif
199+
200+// must do this 'by hand' cause all the std::map stuff doesn't work with msvc6
201+%extend dia::Properties {
202+ dia::IProperty* __getitem__(const char* s) { return self->getitem(s); }
203+
204+ void __setitem__(const char* s, int v) { self->setitem(s, v); }
205+ void __setitem__(const char* s, double v) { self->setitem(s, v); }
206+ void __setitem__(const char* s, const char* v) { self->setitem(s, v); }
207+#ifdef SWIGPYTHON
208+ void __setitem__(const char* s, PyObject* v) {
209+ std::vector<double> vecDouble;
210+ std::vector<dia::IProperty*> vecProp;
211+ if (DiaPythonExtra_ToVector (v, vecDouble))
212+ self->setitem (s, vecDouble);
213+ else if (DiaPythonExtra_ToVector (v, vecProp))
214+ self->setitem (s, vecProp);
215+ else {
216+ PyObject* vs = PyObject_Str (v);
217+ printf ("NOT assigning '%s' = %s\n", s, PyString_AsString (vs));
218+ }
219+ }
220+#endif
221+};
222+
223+%nodefaultctor; // Don't create default constructors
224+%include "dia-connections.h"
225+%clearnodefaultctor; // Re-enable default constructors
226+// again by hand: provide a Python compatible sequence interface
227+%extend dia::Connections {
228+ int __len__ () { return self->len(); }
229+ dia::ConnectionPoint* __getitem__ (int n) { return self->getitem(n); }
230+};
231+%extend dia::Handles {
232+ int __len__ () { return self->len(); }
233+ dia::Handle* __getitem__ (int n) { return self->getitem(n); }
234+};
235+
236+%attribute(dia::Handle, dia::ConnectionPoint*, connected_to, get_connected_to);
237+%attribute(dia::ConnectionPoint, dia::Object*, object, get_object);
238+%extend dia::Objects {
239+ int __len__ () { return self->len(); }
240+ dia::Object* __getitem__ (int n) { return self->getitem(n); }
241+};
242+
243+%nodefaultctor; // Don't create default constructors
244+%ignore dia::Object::bbox;
245+%include "dia-object.h"
246+%clearnodefaultctor; // Re-enable default constructors
247+#ifdef SWIGPYTHON
248+// there may be a target language independent way to do this but not w/o understanding typemaps ;)
249+%extend dia::ObjectType {
250+ // not only creates the object but also two handles to be returned
251+ PyObject* create (double x, double y) {
252+ PyObject* ret = PyTuple_New(3);
253+ dia::Handle *h1, *h2;
254+ dia::Object *o = self->create (x,y, &h1, &h2);
255+ PyTuple_SetItem(ret,0,SWIG_NewPointerObj(o, SWIGTYPE_p_dia__Object, 0));
256+ PyTuple_SetItem(ret,1,SWIG_NewPointerObj(h1, SWIGTYPE_p_dia__Handle, 0));
257+ PyTuple_SetItem(ret,2,SWIG_NewPointerObj(h2, SWIGTYPE_p_dia__Handle, 0));
258+ return ret;
259+ }
260+};
261+%include attribute.i
262+%attribute(dia::Object, _Rectangle, bounding_box, bbox);
263+%extend dia::Object {
264+ // convenience/compatibility taking the position as tuple
265+ PyObject* move_handle (dia::Handle* h, PyObject* pos, int reason, int modifiers)
266+ {
267+ double x = PyFloat_AsDouble(PyTuple_GetItem (pos, 0));
268+ double y = PyFloat_AsDouble(PyTuple_GetItem (pos, 1));
269+ self->move_handle (h, x, y, (HandleMoveReason)reason, (ModifierKeys)modifiers);
270+ Py_INCREF(Py_None);
271+ return Py_None;
272+ }
273+};
274+#endif
275+
276+%nodefaultctor; // Don't create default constructors
277+%include "dia-diagramdata.h"
278+%clearnodefaultctor; // Re-enable default constructors
279+
280+#if 0 // again no partial templates with msvc6
281+%include "std_vector.i"
282+%template(Layers) std::vector<const dia::Layer*>;
283+#else
284+%extend dia::Layers {
285+ int __len__ () { return self->len(); }
286+ dia::Layer* __getitem__ (int n) { return self->getitem(n); }
287+};
288+#endif
289+
290+%nodefaultctor; // Don't create default constructors
291+%include "dia-renderer.h"
292+%clearnodefaultctor; // Re-enable default constructors
293+
294+// afaik SWIG does not support cross language callbacks; so let's build one
295+// NOTE: although renamed above we need to use the old name here
296+%extend _DiaExportFilter {
297+ // don't use 'export' as this produces nothing w/o warning
298+ void do_export (dia::DiagramData *dia, const gchar *filename) {
299+ self->export_func (dia->Self(), filename, filename, self->user_data);
300+ }
301+};
302+
303+%include "dia-extra.h"
304+
305+%ignore _ot_item;
306+#ifdef SWIGPYTHON
307+%inline %{
308+// compatibility functions, just to leave the original plug-ins unchanged
309+void register_import (const char* name, const char* ext, PyObject* user)
310+{
311+ printf ("dia.register_import ('%s', '%s', ...) faked.\n", name, ext);
312+}
313+void register_callback (const char* desc, const char* menu, PyObject* user)
314+{
315+ printf ("dia.register_import ('%s', '%s', ...) faked.\n", desc, menu);
316+}
317+void register_action (const char* desc, const char* action, const char* menu, PyObject* user)
318+{
319+ printf ("dia.register_action ('%s', <%s>'%s', ...) faked.\n", desc, action, menu);
320+}
321+//! callback to be applied on every object in the map
322+static void
323+_ot_item (gpointer key,
324+ gpointer value,
325+ gpointer user_data)
326+{
327+ gchar *name = (gchar *)key;
328+ DiaObjectType *type = (DiaObjectType *)value;
329+ PyObject *dict = (PyObject *)user_data;
330+ PyObject *k, *v;
331+
332+ k = PyString_FromString(name);
333+ v = SWIG_NewPointerObj(type, SWIGTYPE_p_dia__ObjectType, 0);
334+ if (k && v)
335+ PyDict_SetItem(dict, k, v);
336+ Py_XDECREF(k);
337+ Py_XDECREF(v);
338+}
339+PyObject* registered_types ()
340+{
341+ PyObject *dict = PyDict_New();
342+
343+ object_registry_foreach(_ot_item, dict);
344+
345+ return dict;
346+}
347+%}
348+#endif
349+
350+// as long as we are not dependending on app/* - which we dont want! - we need to
351+// fake Display to some extent to make old pydia plug-ins work
352+%pythoncode %{
353+class Display :
354+ def add_update_all (self) :
355+ pass
356+class Diagram :
357+ def __init__ (self) :
358+ self.data = DiagramData ()
359+ def display (self) :
360+ return Display ()
361+ def update_extents (self) :
362+ self.data.update_extents ()
363+ def flush (self) :
364+ pass
365+def new (s) :
366+ return Diagram()
367+def active_display () :
368+ return Display()
369+%}
--- /dev/null
+++ b/bindings/makefile.msc
@@ -0,0 +1,84 @@
1+TOP = ..\..
2+
3+!INCLUDE $(TOP)\glib\build\win32\make.msc
4+
5+!IFNDEF DEBUG
6+PYTHON = ..\..\..\python23
7+#PYTHON = ..\..\..\python25
8+EXTRALIBS = $(PYTHON)\libs\python23.lib user32.lib
9+#EXTRALIBS = $(PYTHON)\Python-2.5\PC\VC6\python25.lib user32.lib
10+!ELSE
11+PYTHON = ..\..\..\python25
12+EXTRALIBS = $(PYTHON)\Python-2.5\PC\VC6\python25_d.lib user32.lib
13+!ENDIF
14+
15+INCLUDES = \
16+ -I.. \
17+ -I..\lib \
18+ -I..\app
19+
20+SWIG_FLAGS = $(INCLUDES)
21+
22+# we don't depend on Gtk at runtime, but some dia headers need it at compile time
23+CFLAGS = -FImsvc_recommended_pragmas.h \
24+!IFDEF DEBUG
25+ -D_DEBUG=1 \
26+!ENDIF
27+ -DHAVE_CONFIG_H $(INCLUDES) \
28+ -I$(PYTHON)\include $(GLIB_CFLAGS) $(GTK2_CFLAGS) $(INTL_CFLAGS) \
29+ $(LIBXML2_CFLAGS)
30+
31+CPPFLAGS = $(CFLAGS) -GX -GR -Zi
32+
33+EXTRALIBS = $(EXTRALIBS) $(LIBXML2_LIBS) $(INTL_LIBS) $(PANGO_LIBS) \
34+ ..\lib\libdia.lib ..\app\dia-app.lib
35+
36+GENERATED = \
37+ dia-python.cpp \
38+# csharp\dia-csharp.cpp \
39+# csharp\*.cs \
40+
41+INTERFACES = \
42+ dia.swig \
43+ dia-properties.h \
44+ dia-object.h \
45+ dia-renderer.h \
46+ dia-diagramdata.h \
47+ dia-connections.h \
48+
49+OBJECTS = \
50+ dia-connections.obj \
51+ dia-properties.obj \
52+ dia-object.obj \
53+ dia-renderer.obj \
54+ dia-diagramdata.obj \
55+ \
56+ dia-extra.obj \
57+ \
58+ dia-python-extra.obj
59+
60+all : \
61+ _dia.pyd \
62+
63+other : \
64+ dia-csharp.cpp \
65+ dia-xml.cpp \
66+ dia-perl.cpp \
67+
68+dia-python.cpp : $(INTERFACES)
69+ swig $(SWIG_FLAGS) -python -modern -extranative -c++ -o $*.cpp dia.swig
70+
71+dia-csharp.cpp : $(INTERFACES)
72+ swig $(SWIG_FLAGS) -csharp -c++ -o csharp\$*.cpp dia.swig
73+
74+dia-xml.cpp : $(INTERFACES)
75+ swig $(SWIG_FLAGS) -xml -c++ -o xml\$*.cpp dia.swig
76+
77+dia-perl.cpp : $(INTERFACES)
78+ swig $(SWIG_FLAGS) -perl -c++ -o perl\$*.cpp dia.swig
79+
80+_dia.pyd : $(OBJECTS) dia-python.obj
81+ $(CC) $(CFLAGS) -LD -Fe$@ $(OBJECTS) dia-python.obj $(LDFLAGS) $(EXTRALIBS) $(GLIB_LIBS)
82+
83+clean::
84+ del _dia.pyd dia.py dia.pyc $(GENERATED)
--- /dev/null
+++ b/bindings/test.py
@@ -0,0 +1,133 @@
1+import dia
2+# a global object to make it changeable by main()
3+format_extensions = ["wmf", "svg", "png"]
4+
5+def Dump () :
6+ print dir(dia)
7+
8+ r = dia.Rectangle
9+ print r, dir(r)
10+ o = dia.Object
11+ print o, dir(o)
12+ rd = dia.Renderer
13+ print rd, dir(rd)
14+
15+import sys
16+sys.path.insert(0, r'd:\graph\dia2\python')
17+sys.path.insert(0, r'..\plug-ins\python')
18+
19+import os
20+os.environ["DIA_LIB_PATH"] = r"d:\graph\dia2\dia"
21+dia.register_plugins()
22+
23+def Export (name, data) :
24+ # write data to file, the format is choosen here
25+ for ext in format_extensions :
26+ ef = dia.filter_guess_export_filter (name + "." + ext)
27+ if ef :
28+ ef.do_export (data, name + "." + ext)
29+ break
30+
31+def Import () :
32+ data = dia.DiagramData()
33+ import diasvg_import
34+ diasvg_import.import_svg (r"D:\graph\dia2\render-test.svg", data)
35+
36+ filename = "render-test-swig.svg"
37+ ef = dia.filter_get_by_name ("svg")
38+ if not ef :
39+ print "Guessing ..."
40+ ef = dia.filter_guess_export_filter ("dummy.png")
41+ filename = "render-test-swig.png"
42+
43+ print ef, "\n", ef.description, "\n", dir(ef)
44+
45+ ef.do_export (data, filename)
46+
47+def Gx () :
48+ data = dia.DiagramData()
49+
50+ import diagx
51+ diagx.ImportXml (r'D:\data\work\camera\Dp70Camera.xml', data)
52+ Export ("gx-test", data)
53+
54+def Doc () :
55+ data = dia.DiagramData()
56+
57+ import pydiadoc
58+ data = pydiadoc.autodoc_cb (data, 0)
59+ Export ("pydiadoc", data)
60+
61+def Dox () :
62+ data = dia.DiagramData()
63+
64+ import doxrev
65+ #doxrev.import_file (r'D:\data\work\dev\include\obscam\xml\classOBS_1_1ICamera.xml', data)
66+ doxrev.import_files (r'D:\data\work\dev\include\obscam\xml\classOBS_1_1ICamera.xml', data)
67+ data.update_extents()
68+ Export ("doxrev-test", data)
69+
70+def Types () :
71+ data = dia.DiagramData()
72+
73+ import otypes
74+ data = otypes.otypes_cb (data, 0)
75+ Export ("otypes", data)
76+
77+def AObj () :
78+ data = dia.DiagramData()
79+
80+ import aobjects
81+ data = aobjects.aobjects_cb (data, 0)
82+ Export ("aobjs", data)
83+
84+def Gen () :
85+ data = dia.DiagramData()
86+
87+ import gendia
88+ data = gendia.dia_generate_dia_cb (data, 0)
89+ Export ("gendia", data)
90+def DRaw () :
91+ data = dia.DiagramData()
92+ # create something interesting to save
93+ if 0 :
94+ import aobjects
95+ data = aobjects.aobjects_cb (data, 0)
96+ else :
97+ import pydiadoc
98+ data = pydiadoc.autodoc_cb (data, 0)
99+ import diaraw
100+ r = diaraw.DiaOutRenderer()
101+ r.begin_render (data, "diaraw.dia")
102+ r.end_render ()
103+
104+def Self () :
105+ data = dia.DiagramData()
106+ r = data.extents
107+ try :
108+ data.extents = r
109+ except AttributeError, s :
110+ print "Expected except", s, r.top, r.left
111+
112+for arg in sys.argv :
113+ if '--dump' == arg : Dump ()
114+ elif '--import' == arg : Import ()
115+ elif '--gx' == arg : Gx ()
116+ elif '--doc' == arg : Doc ()
117+ elif '--dox' == arg : Dox ()
118+ elif '--types' == arg : Types ()
119+ elif '--aobj' == arg : AObj ()
120+ elif '--gen' == arg : Gen ()
121+ elif '--self' == arg : Self ()
122+ elif '--draw' == arg : DRaw ()
123+ elif '--all' == arg :
124+ Dump()
125+ Import()
126+ Gx()
127+ Doc()
128+ Dox()
129+ Types()
130+ AObj ()
131+ Gen()
132+ DRaw()
133+ else : format_extensions.insert(0, arg)