作図ソフト dia の改良版
Revisión | 414c14ea85d8f81fbc0b3392ba3ceaaaed0486d1 (tree) |
---|---|
Tiempo | 2007-03-27 05:18:26 |
Autor | Hans Breuer <hans@breu...> |
Commiter | Hans Breuer |
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
@@ -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 | + | |
1 | 6 | 2007-03-25 Lars Clausen <lars@raeder.dk> |
2 | 7 | |
3 | 8 | * NEWS: |
@@ -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 |
@@ -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 |
@@ -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 | +} |
@@ -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 */ |
@@ -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 | +} |
@@ -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 */ |
@@ -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 | +} |
@@ -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 | +} |
@@ -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 | +} |
@@ -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 */ |
@@ -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 | +} |
@@ -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 */ |
@@ -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 | +} |
@@ -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 |
@@ -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 | +} |
@@ -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 */ |
@@ -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 | +%} |
@@ -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) |
@@ -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) |