1 /* Dia -- an diagram creation/manipulation program -*- c -*-
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /** @file object.h -- definitions for Dia objects, in particular the 'virtual'
20  * functions and the object and type structures.
21  */
22 #ifndef OBJECT_H
23 #define OBJECT_H
24 
25 #include "diatypes.h"
26 #include <gtk/gtk.h>
27 
28 #include "geometry.h"
29 #include "connectionpoint.h"
30 #include "handle.h"
31 #include "diamenu.h"
32 #include "objchange.h"
33 #include "dia_xml.h"
34 #include "text.h"
35 
36 G_BEGIN_DECLS
37 
38 /** Flags for DiaObject */
39 /** Set this if the DiaObject can 'contain' other objects that move with
40  *  it, a.k.a. be a parent.  A parent moves its children along and
41  *  constricts its children to live inside its borders.
42  */
43 #define DIA_OBJECT_CAN_PARENT 1
44 /** Set this if the DiaObject grabs all input destined for its children.
45  * This is typically used for group-like objects.
46  */
47 #define DIA_OBJECT_GRABS_CHILD_INPUT 2
48 /** Set this if the DiaObject expands/contracts when children are
49  * moved/modified/added/deleted */
50 #define DIA_OBJECT_EXPAND_WITH_CHILDREN 4
51 
52 /** This enumeration gives a bitset of modifier keys currently held down.
53  */
54 typedef enum {
55   MODIFIER_NONE,
56   MODIFIER_LEFT_SHIFT,
57   MODIFIER_RIGHT_SHIFT,
58   MODIFIER_SHIFT,
59   MODIFIER_LEFT_ALT = 4,
60   MODIFIER_RIGHT_ALT = 8,
61   MODIFIER_ALT = 12,
62   MODIFIER_LEFT_CONTROL = 16,
63   MODIFIER_RIGHT_CONTROL = 32,
64   MODIFIER_CONTROL = 48
65 } ModifierKeys;
66 
67 /************************************
68  ** Some general function prototypes
69  **
70  ** These are the prototypes for the
71  ** functions that must be defined for
72  ** every object we can insert in a
73  ** diagram.
74  **
75  ************************************/
76 
77 /*** Object type (class) operations ***/
78 
79 /** Function called to create an object.
80  *  This function is responsible for allocation memory for the object.
81  *  This is one of the object class functions.
82  * @param startpoint : initial position for the object
83  * @param user_data  : Can be used to pass extra params to the creation
84  *                of the object. Can be used to have two icons of
85  *                the same object that are instansiated a bit different.
86  * @param handle1    : (return) Handle connected to startpoint
87  * @param handle2    : (return) Handle dragged on creation
88  *  both handle1 and handle2 can be NULL
89  * @return A newly created object.
90 */
91 typedef DiaObject* (*CreateFunc) (Point *startpoint,
92 			       void *user_data,
93 			       Handle **handle1,
94 			       Handle **handle2);
95 
96 /** This function load the object's data from file fd. No header has to be
97  *  skipped. The data should be read using the functions in lib/files.h
98  *  The memory for the object has to be allocated (see CreateFunc)
99  *  The version number is the version number of the DiaObjectType that was saved.
100  *  This must be used to maintain backwards compatible if you change some
101  *  in the save format. All objects must be capable of reading all earlier
102  *  version.
103  *  This is one of the object class functions.
104  * @param obj_node A node in an XML object to load from.
105  * @param version The version of the object found in the XML file.
106  * @param filename The name of the file we're loading from, for use in
107  *                 error messages.
108  */
109 typedef DiaObject* (*LoadFunc) (ObjectNode obj_node, int version,
110 				const char *filename);
111 
112 /** This function save the object's data to file fd. No header is required.
113  *  The data should be written using the functions in lib/files.h
114  *  This is one of the object class functions.
115  * @param obj An object to save.
116  * @param obj_node An XML node to save it in.
117  * @param filename The name of the file we're saving to, for use in error
118  *                 messages.
119  */
120 typedef void (*SaveFunc) (DiaObject* obj, ObjectNode obj_node,
121 			  const char *filename);
122 
123 /** Function called when the user has double clicked on an Tool.
124  *  When this function is called and the dialog already is created,
125  *  make sure to update the values in the widgets so that it
126  *  accurately describes the current state of the tool.
127  *  This is one of the object class functions.
128  * @return a dialog that the user can use to edit the defaults for new
129  * objects of this type.
130 */
131 typedef GtkWidget *(*GetDefaultsFunc) ();
132 
133 /** Function called when the user clicks Apply on an edit defaults dialog.
134  * This is currently not used by any object.
135  * This is one of the object class functions.
136  */
137 typedef void *(*ApplyDefaultsFunc) ();
138 
139 /*** Object operations ***/
140 
141 /** Function called before an object is deleted.
142  *  This function must call the parent class's DestroyFunc, and then free
143  *  the memory associated with the object, but not the object itself
144  *  Must also unconnect itself from all other objects.
145  *  (This is by calling object_destroy, or letting the super-class call it)
146  *  This is one of the object_ops functions.
147  * @param obj An object to destroy.
148  */
149 typedef void (*DestroyFunc) (DiaObject* obj);
150 
151 
152 /** Function responsible for drawing the object.
153  *  Every drawing must be done through the use of the Renderer, so that we
154  *  can render the picture on screen, in an eps file, ...
155  *  This is one of the object_ops functions.
156  * @param The object to draw.
157  * @param The renderer object to draw with.
158  */
159 typedef void (*DrawFunc) (DiaObject* obj, DiaRenderer* ddisp);
160 
161 
162 /** This function must return the distance between the DiaObject and the Point.
163  *  Several functions are provided in geometry.h to facilitate this calculus.
164  *  This is one of the object_ops functions.
165  * @param obj The object.
166  * @param point A point to give the distance to.
167  * @return The distance from the point to the nearest part of the object.
168  *         If the point is inside a closed object, return 0.0.
169  */
170 typedef real (*DistanceFunc) (DiaObject* obj, Point* point);
171 
172 
173 /** Function called once the object has been selected.
174  *  Basically, this function should update the object (position of the
175  *  handles,...)  This is one of the object_ops functions.
176  *  This function should not redraw the object.
177  * @param obj An object that is being selected.
178  * @param clicked_point is the point on the screen where the user has clicked
179  * @param interactive_renderer is a renderer that has some extra functions
180  *                        most notably the possibility to get EXACT
181  *			 measures of strings. Used to place cursors
182  *			 and other interactive stuff.
183  *			 (Don't draw to the renderer)
184  */
185 typedef void (*SelectFunc) (DiaObject*   obj,
186 			    Point*    clicked_point,
187 			    DiaRenderer* interactive_renderer);
188 
189 /** Returns a copy of DiaObject.
190  *  This must be an depth-copy (pointers must be duplicated and so on)
191  *  as the initial object can be deleted any time.
192  *  This is one of the object_ops functions.
193  * @param obj An object to make a copy of.
194  * @return A newly allocated object copied from `obj', but without any
195  *         connections to other objects.
196  */
197 typedef DiaObject* (*CopyFunc) (DiaObject* obj);
198 
199 /** Function called to move the entire object.
200  *  This is one of the object_ops functions.
201  * @param obj The object being moved.
202  * @param pos Where the object is being moved to.
203  *  Its exact definition depends on the object. It is the point on the
204  *  object that 'snaps' to the grid if that is enabled. (generally it
205  *  is the upper left corner)
206  * @return An ObjectChange* with additional undo information, or
207  * (in most cases) NULL.  Undo for moving the object itself is handled
208  * elsewhere.
209  */
210 typedef ObjectChange* (*MoveFunc) (DiaObject* obj, Point * pos);
211 
212 /** Function called to move one of the handles associated with the
213  *  object.  This is one of the object_ops functions.
214  * @param obj The object whose handle is being moved.
215  * @param handle The handle being moved.
216  * @param pos The position it has been moved to (corrected for
217  *   vertical/horizontal only movement).
218  * @param cp If non-NULL, the connectionpoint found at this position.
219  *   If @a cp is NULL, there may or may not be a connectionpoint.
220  * @param The reason the handle was moved.
221  *     - HANDLE_MOVE_USER means the user is dragging the point.
222  *     - HANDLE_MOVE_USER_FINAL means the user let go of the point.
223  *     - HANDLE_MOVE_CONNECTED means it was moved because something
224  *	    it was connected to moved.
225  * @param modifiers gives a bitset of modifier keys currently held down
226  *     - MODIFIER_SHIFT is either shift key
227  *     - MODIFIER_ALT is either alt key
228  *     - MODIFIER_CONTROL is either control key
229  *	    Each has MODIFIER_LEFT_* and MODIFIER_RIGHT_* variants
230  * @return An @a ObjectChange* with additional undo information, or
231  *  (in most cases) NULL.  Undo for moving the handle itself is handled
232  *  elsewhere.
233  */
234 typedef ObjectChange* (*MoveHandleFunc) (DiaObject*          obj,
235 					 Handle*          handle,
236 					 Point*           pos,
237 					 ConnectionPoint* cp,
238 					 HandleMoveReason reason,
239 					 ModifierKeys     modifiers);
240 
241 /** Function called when the user has double clicked on an DiaObject.
242  *  This is one of the object_ops functions.
243  * @param obj An obj that this dialog is being made for.
244  * @param is_default If true, this dialog is for object defaults, and
245  * the toolbox options should not be shown.
246  * @return A dialog to edit the properties of the object.
247  * When this function is called and the dialog already is created,
248  * make sure to update the values in the widgets so that it
249  * accurately describes the current state of the object.
250  * Remember to destroy this dialog when the object is destroyed!
251 
252  * Note that if you want to use the same dialog multiple times,
253  * you should ref it first.  Just run the following on the widget
254  * when you create it:
255  *   gtk_object_ref(GTK_OBJECT(widget));
256  *   gtk_object_sink(GTK_OBJECT(widget)); / * optional, but recommended * /
257  * If you don't do this, the widget will be destroyed when the
258  * properties dialog is closed.
259  */
260 typedef GtkWidget *(*GetPropertiesFunc) (DiaObject* obj, gboolean is_default);
261 
262 /** This function is called when the user clicks on
263  *  the "Apply" button.  The widget parameter is the one created by
264  *  the get_properties function.
265  *  This is one of the object_ops functions.
266  * @param obj The object whose dialog has had its Apply button clicked.
267  * @param widget The properties dialog being applied.
268  * @return a Change that can be used for undo/redo.
269  * The returned change is already applied.
270  */
271 typedef ObjectChange *(*ApplyPropertiesDialogFunc) (DiaObject* obj, GtkWidget *widget);
272 
273 /** This function is used to apply a list of properties to the current
274  *  object. It is typically called by ApplyPropertiesDialogFunc. This
275  *  is different from SetPropsFunc since this is used to implement
276  *  undo/redo.
277  *  This is one of the object_ops functions.
278  * @param obj The object to which properties are to be applied
279  * @param props The list of properties that are to be applied
280  * @return a Change for undo/redo
281  */
282  typedef ObjectChange *(*ApplyPropertiesListFunc) (DiaObject* obj, GPtrArray* props);
283 
284 /** Desribe the properties that this object supports.
285  *  This is one of the object_ops functions.
286  * @param obj The object whose properties we want described.
287  * @return a NULL-terminated array of property descriptions.
288  * As the const return implies the returned data is not owned by  the
289  * caller. If this function returns a dynamically created description,
290  * then DestroyFunc must free the description.
291  */
292 typedef const PropDescription *(* DescribePropsFunc) (DiaObject *obj);
293 
294 /** Get the actual values of the properties given.
295  * Note that the props array need not contain all the properties
296  * defined for the object, nor do all the properties in the array need be
297  * defined for the object.  All properties in the props array that are
298  * actually set will be set.
299  * This is one of the object_ops functions.
300  * @param obj An object that delivers the values.
301  * @param props A list of Property objects whose values are to be set based
302  *              on the objects internal data.  The types for the objects are
303  *              also being set as a side-effect.
304  */
305 typedef void (* GetPropsFunc) (DiaObject *obj, GPtrArray *props);
306 
307 /** Set the object to have the values defined in the properties list.
308  * Note that the props array may contain more or fewer properties than the
309  * object defines, but only and all the ones defined for the object will
310  * be applied to the object.
311  * This is one of the object_ops functions.
312  * @param obj An object to update values on.
313  * @param props An array of Property objects whose values are to be set on
314  *              the object.
315  */
316 typedef void (* SetPropsFunc) (DiaObject *obj, GPtrArray *props);
317 
318 /** Return an object-specific menu with toggles etc. properly set.
319  * This is one of the object_ops functions.
320  * @param obj The object that is selected when the object menu is asked for.
321  * @param position Where the user clicked.  This can be used to place whatever
322  * the menu point may create, such as new segment corners.
323  * @return A menu description with values set appropriately for this object.
324  * The description object must not be freed by the caller.
325  */
326 typedef DiaMenu *(*ObjectMenuFunc) (DiaObject* obj, Point *position);
327 
328 /** Function for updates on a text part of an object.  This function, if
329  * not null, will be called every time the text is changed or editing
330  * starts or stops.
331  * This is one of the object_ops functions.
332  * @param obj The self object
333  * @param text The text entry being edited
334  * @param state The state of the editing, either TEXT_EDIT_START,
335  * TEXT_EDIT_INSERT, TEXT_EDIT_DELETE, or TEXT_EDIT_END.
336  * @param textchange For TEXT_EDIT_INSERT, the text about to be inserted.
337  * For TEXT_EDIT_DELETE, the text about to be deleted.
338  * @return For TEXT_EDIT_INSERT and TEXT_EDIT_DELETE, TRUE this change
339  * will be allowed, FALSE otherwise.  For TEXT_EDIT_START and TEXT_EDIT_END,
340  * the return value is ignored.
341  */
342 typedef gboolean (*TextEditFunc) (DiaObject *obj, Text *text, TextEditState state, gchar *textchange);
343 
344 /*************************************
345  **  The functions provided in object.c
346  *************************************/
347 
348 void object_init(DiaObject *obj, int num_handles, int num_connections);
349 void object_destroy(DiaObject *obj); /* Unconnects handles, so don't
350 					    free handles before calling. */
351 void object_copy(DiaObject *from, DiaObject *to);
352 
353 void object_save(DiaObject *obj, ObjectNode obj_node);
354 void object_load(DiaObject *obj, ObjectNode obj_node);
355 
356 GList *object_copy_list(GList *list);
357 ObjectChange* object_list_move_delta_r(GList *objects, Point *delta, gboolean affected);
358 ObjectChange* object_list_move_delta(GList *objects, Point *delta);
359 /** Rotate an object around a point.  If center is NULL, the position of
360  * the object is used. */
361 ObjectChange* object_list_rotate(GList *objects, Point *center, real angle);
362 /** Scale an object around a point.  If center is NULL, the position of
363  * the object is used. */
364 ObjectChange* object_list_scale(GList *objects, Point *center, real factor);
365 void destroy_object_list(GList *list);
366 void object_add_handle(DiaObject *obj, Handle *handle);
367 void object_add_handle_at(DiaObject *obj, Handle *handle, int pos);
368 void object_remove_handle(DiaObject *obj, Handle *handle);
369 void object_add_connectionpoint(DiaObject *obj, ConnectionPoint *conpoint);
370 void object_remove_connectionpoint(DiaObject *obj,
371 				   ConnectionPoint *conpoint);
372 void object_add_connectionpoint_at(DiaObject *obj,
373 				   ConnectionPoint *conpoint,
374 				   int pos);
375 void object_connect(DiaObject *obj, Handle *handle,
376 		    ConnectionPoint *conpoint);
377 void object_unconnect(DiaObject *connected_obj, Handle *handle);
378 void object_remove_connections_to(ConnectionPoint *conpoint);
379 void object_unconnect_all(DiaObject *connected_obj);
380 void object_registry_init(void);
381 void object_register_type(DiaObjectType *type);
382 void object_registry_foreach(GHFunc func, gpointer  user_data);
383 DiaObjectType *object_get_type(char *name);
384 gchar *object_get_displayname (DiaObject* obj);
385 gboolean object_flags_set(DiaObject* obj, gint flags);
386 
387 /* These functions can be used as a default implementation for an object which
388    can be completely described, loaded and saved through standard properties.
389 */
390 DiaObject *object_load_using_properties(const DiaObjectType *type,
391                                      ObjectNode obj_node, int version,
392                                      const char *filename);
393 void object_save_using_properties(DiaObject *obj, ObjectNode obj_node,
394                                   int version, const char *filename);
395 DiaObject *object_copy_using_properties(DiaObject *obj);
396 
397 /*****************************************
398  **  The structures used to define an object
399  *****************************************/
400 
401 /**
402  * \private This is currently unused
403  *
404  * This structure defines an affine transformation that has been applied
405  * to this object.  Affine transformations done on a group are performed
406  * on all objects in the group.
407  */
408 typedef struct _Affine {
409   real rotation;
410   real scale;
411   real translation;
412 } Affine;
413 
414 
415 /*!
416   \brief _DiaObject vtable
417 
418   This structure gives access to the functions used to manipulate an object
419   See information above on the use of the functions
420 */
421 struct _ObjectOps {
422   DestroyFunc         destroy;
423   DrawFunc            draw;
424   DistanceFunc        distance_from;
425   SelectFunc          selectf;
426   CopyFunc            copy;
427   MoveFunc            move;
428   MoveHandleFunc      move_handle;
429   GetPropertiesFunc   get_properties;
430   ApplyPropertiesDialogFunc  apply_properties_from_dialog;
431   ObjectMenuFunc      get_object_menu;
432 
433   DescribePropsFunc   describe_props;
434   GetPropsFunc        get_props;
435   SetPropsFunc        set_props;
436 
437   TextEditFunc        edit_text;
438 
439   ApplyPropertiesListFunc apply_properties_list;
440 
441   /*!
442     Unused places (for extension).
443     These should be NULL for now. In the future they might be used.
444     Then an older object will be binary compatible, because all new code
445     checks if new ops are supported (!= NULL)
446   */
447   void      (*(unused[4]))(DiaObject *obj,...);
448 };
449 
450 /*!
451   \class _DiaObject
452 
453   \brief Base class for all of Dia's objects, i.e. diagram building blocks
454 
455   The base class in the DiaObject hierarchy.
456   All information in this structure read-only
457   from the application point of view except
458   when connection objects. (Then handles and
459   connections are changed).
460 
461   position is not necessarly the corner of the object, but rather
462   some 'good' spot on it which will be natural to snap to.
463 */
464 struct _DiaObject {
465   DiaObjectType    *type; /*!< pointer to the registered type */
466   Point             position; /*!<  often but not necessarily the upper left corner of the object */
467   /** The area that contains all parts of the 'real' object, i.e. the parts
468    *  that would be printed, exported to pixmaps etc.  This is also used to
469    *  determine the size of autofit scaling, so it should be as large as
470    *  the objects without interactive bits and preferably no larger.
471    *  The bounding_box will always contain this box.
472    *  Do not access this field directly, but use dia_object_get_enclosing_box().
473    */
474   Rectangle         bounding_box;
475   Affine            affine; /*!< unused */
476 
477   int               num_handles;
478   Handle          **handles;
479 
480   int               num_connections;
481   ConnectionPoint **connections;
482 
483   ObjectOps *ops; /*!< pointer to the vtable */
484 
485   Layer *parent_layer; /*< Back-pointer to the owning layer.
486 			   This may only be set by functions internal to
487 			   the layer, and accessed via
488 			   dia_object_get_parent_layer() */
489   DiaObject *parent; /*!< Back-pointer to DiaObject which is parenting this object. Can be NULL */
490   GList *children; /*!< In case this object is a parent of other object the children are listed here */
491   gint flags; /*!< Various flags that can be set for this object, see defines above */
492 
493   Color *highlight_color; /*!< The color that this object is currently
494 			       highlighted with, or NULL if it is not
495 			       highlighted. */
496   /** The area that contains all parts rendered interactively, so includes
497    *  handles, bezier controllers etc.  Despite historical difference, this
498    *  should not be accessed directly, but through dia_object_get_bounding_box().
499    *  Note that handles and connection points are not included by this, but
500    *  added by that which needs it.
501    *  Internal:  If this is set to a 0x0 box, returns bounding_box.  That is for
502    *  those objects that don't actually calculate it, but can just use the BB.
503    *  Since handles and CPs are not in the BB, that will be the case for most
504    *  objects.
505    */
506   Rectangle         enclosing_box;
507   /** Metainfo of the object, should not be manipulated directy */
508   GHashTable       *meta;
509 };
510 
511 /*!
512  * \brief Vtable for _DiaObjectType
513  */
514 struct _ObjectTypeOps {
515   CreateFunc        create;
516   LoadFunc          load;
517   SaveFunc          save;
518   GetDefaultsFunc   get_defaults;
519   ApplyDefaultsFunc apply_defaults;
520   /*
521     Unused places (for extension).
522     These should be NULL for now. In the future they might be used.
523     Then an older object will be binary compatible, because all new code
524     checks if new ops are supported (!= NULL)
525   */
526   void      (*(unused[10]))(DiaObject *obj,...);
527 };
528 
529 /*!
530    \brief _DiaObject factory
531 
532    Structure so that the ObjectFactory can create objects
533    of unknown type. (Read in from a shared lib.)
534  */
535 struct _DiaObjectType {
536 
537   char *name; /*!< The type name should follow a pattern of '<module> - <class>' like "UML - Class" */
538   int version; /*!< DiaObjects must be backward compatible, i.e. support possibly older versions formats */
539 
540   char **pixmap; /* Also put a pixmap in the sheet_object.
541 		    This one is used if not in sheet but in toolbar.
542 		    Stored in xpm format */
543 
544   ObjectTypeOps *ops; /*!< pointer to the vtable */
545 
546   char *pixmap_file; /* fallback if pixmap is NULL */
547   void *default_user_data; /* use this if no user data is specified in
548 			      the .sheet file */
549 };
550 
551 /* base property stuff ... */
552 #define OBJECT_COMMON_PROPERTIES \
553   { "obj_pos", PROP_TYPE_POINT, PROP_FLAG_OPTIONAL, \
554     "Object position", "Where the object is located"}, \
555   { "obj_bb", PROP_TYPE_RECT, PROP_FLAG_OPTIONAL, \
556     "Object bounding box", "The bounding box of the object"}, \
557   { "meta", PROP_TYPE_DICT, PROP_FLAG_OPTIONAL, \
558     "Object meta info", "Some key/value pairs"}
559 
560 #define OBJECT_COMMON_PROPERTIES_OFFSETS \
561   { "obj_pos", PROP_TYPE_POINT, offsetof(DiaObject, position) }, \
562   { "obj_bb", PROP_TYPE_RECT, offsetof(DiaObject, bounding_box) }, \
563   { "meta", PROP_TYPE_DICT, offsetof(DiaObject, meta) }
564 
565 
566 gboolean       dia_object_defaults_load (const gchar *filename,
567                                          gboolean create_lazy);
568 DiaObject  *dia_object_default_get  (const DiaObjectType *type, gpointer user_data);
569 DiaObject  *dia_object_default_create (const DiaObjectType *type,
570                                     Point *startpoint,
571                                     void *user_data,
572                                     Handle **handle1,
573                                     Handle **handle2);
574 gboolean         dia_object_defaults_save (const gchar *filename);
575 Layer           *dia_object_get_parent_layer(DiaObject *obj);
576 gboolean         dia_object_is_selected (const DiaObject *obj);
577 const Rectangle *dia_object_get_bounding_box(const DiaObject *obj);
578 const Rectangle *dia_object_get_enclosing_box(const DiaObject *obj);
579 DiaObject       *dia_object_get_parent_with_flags(DiaObject *obj, guint flags);
580 gboolean         dia_object_is_selectable(DiaObject *obj);
581 /* The below are for debugging purposes only. */
582 gboolean   dia_object_sanity_check(const DiaObject *obj, const gchar *msg);
583 
584 /** A standard definition of a function that takes a DiaObject */
585 typedef void (*DiaObjectFunc) (const DiaObject *obj);
586 
587 /** convenience functions for meta info */
588 void   dia_object_set_meta (DiaObject *obj, const gchar *key, const gchar *value);
589 gchar *dia_object_get_meta (DiaObject *obj, const gchar *key);
590 
591 G_END_DECLS
592 
593 #endif /* OBJECT_H */
594 
595 
596