1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * object_defaults.c : manage default properties of dia objects
5 * The serialization is done with standard object methods in
6 * a diagram compatible format.
8 * Copyright (C) 2002 Hans Breuer
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <stdlib.h> /* atoi() */
33 #include <libxml/tree.h>
34 #include "dia_xml_libxml.h"
40 static GHashTable
*defaults_hash
= NULL
;
41 static gboolean object_default_create_lazy
= FALSE
;
44 _obj_create (gpointer key
,
48 gchar
*name
= (gchar
*)key
;
49 ObjectType
*type
= (ObjectType
*)value
;
50 GHashTable
*ht
= (GHashTable
*) user_data
;
52 Point startpoint
= {0.0,0.0};
53 Handle
*handle1
,*handle2
;
55 g_assert (g_hash_table_lookup (ht
, name
) == NULL
);
57 /* at least 'Group' has no ops */
61 /* the custom objects needs extra_data */
62 obj
= type
->ops
->create(&startpoint
, type
->default_user_data
, &handle1
,&handle2
);
64 g_warning ("Failed to create default object for '%s'", name
);
65 else if (0 != strcmp (obj
->type
->name
, name
))
66 object_destroy (obj
); /* Skip over 'compatibility' names/objects */
68 g_hash_table_insert(ht
, obj
->type
->name
, obj
);
72 _obj_destroy (gpointer val
)
74 Object
*obj
= (Object
*)val
;
76 obj
->ops
->destroy (obj
);
80 * dia_object_defaults_load :
81 * @filename : the file to load from or NULL for default
82 * @create_lazy : if FALSE creates default objects for
83 * every known type. Otherwise default objects
84 * are created on demand
86 * Create all the default objects.
89 dia_object_defaults_load (const gchar
*filename
, gboolean create_lazy
)
93 ObjectNode obj_node
, layer_node
;
95 object_default_create_lazy
= create_lazy
;
99 defaults_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
103 object_registry_foreach (_obj_create
, defaults_hash
);
107 /* overload properties from file */
110 gchar
*default_filename
= dia_config_filename("defaults.dia");
111 doc
= xmlDiaParseFile(default_filename
);
112 g_free (default_filename
);
115 doc
= xmlDiaParseFile(filename
);
120 name_space
= xmlSearchNs(doc
, doc
->xmlRootNode
, "dia");
121 if ( strcmp (doc
->xmlRootNode
->name
, "diagram")
122 || (name_space
== NULL
))
124 message_error(_("Error loading defaults '%s'.\n"
125 "Not a Dia diagram file."), filename
);
130 layer_node
= doc
->xmlRootNode
->xmlChildrenNode
;
133 if ( !xmlIsBlankNode(layer_node
)
134 && 0 == strcmp(layer_node
->name
, "layer"))
136 obj_node
= layer_node
->xmlChildrenNode
;
139 if ( !xmlIsBlankNode(obj_node
)
140 && 0 == strcmp(obj_node
->name
, "object"))
142 char *typestr
= xmlGetProp(obj_node
, "type");
143 char *version
= xmlGetProp(obj_node
, "version");
146 Object
*obj
= g_hash_table_lookup (defaults_hash
, typestr
);
150 g_warning ("Unknown object '%s' while reading '%s'",
154 ObjectType
*type
= object_get_type (typestr
);
156 obj
= type
->ops
->load (
158 version
? atoi(version
) : 0,
161 g_hash_table_insert (defaults_hash
,
162 obj
->type
->name
, obj
);
167 #if 0 /* lots of complaining about missing attributes */
168 object_load_props(obj
, obj_node
); /* leaks ?? */
171 def_obj
= obj
->type
->ops
->load (
173 version
? atoi(version
) : 0,
175 if (def_obj
->ops
->set_props
)
177 object_copy_props (obj
, def_obj
, FALSE
);
178 def_obj
->ops
->destroy (def_obj
);
182 /* can't copy props */
183 g_hash_table_replace (defaults_hash
,
184 def_obj
->type
->name
, def_obj
);
193 obj_node
= obj_node
->next
;
196 layer_node
= layer_node
->next
;
204 * Remember as defaults from a diagram object
207 dia_object_default_make (const Object
*obj_from
)
211 g_return_if_fail (obj_from
);
213 obj_to
= dia_object_default_get (obj_from
->type
);
214 g_return_if_fail (obj_to
);
216 object_copy_props (obj_to
, obj_from
, TRUE
);
220 * dia_object_default_get :
221 * @type : the ObjectType
223 * Allows to edit one defaults object properties
226 dia_object_default_get (const ObjectType
*type
)
230 obj
= g_hash_table_lookup (defaults_hash
, type
->name
);
231 if (!obj
&& object_default_create_lazy
)
233 Point startpoint
= {0.0,0.0};
234 Handle
*handle1
,*handle2
;
236 /* at least 'Group' has no ops */
240 /* the custom objects needs extra_data */
241 obj
= type
->ops
->create(&startpoint
,
242 type
->default_user_data
,
245 g_hash_table_insert (defaults_hash
, obj
->type
->name
, obj
);
252 * dia_object_default_create:
253 * @type : the objects type
254 * @startpoint : the left upper corner
259 * Create an object respecting defaults if available
262 dia_object_default_create (const ObjectType
*type
,
268 const Object
*def_obj
;
271 g_return_val_if_fail (type
!= NULL
, NULL
);
273 def_obj
= dia_object_default_get (type
);
276 /* copy properties to new object, but keep position */
277 obj
= type
->ops
->create (startpoint
, user_data
, handle1
, handle2
);
280 object_copy_props (obj
, def_obj
, TRUE
);
281 obj
->ops
->move (obj
, startpoint
);
286 obj
= type
->ops
->create (startpoint
, user_data
, handle1
, handle2
);
292 typedef struct _MyLayerInfo MyLayerInfo
;
299 typedef struct _MyRootInfo MyRootInfo
;
304 GHashTable
*layer_hash
;
310 _obj_store (gpointer key
,
314 gchar
*name
= (gchar
*)key
;
315 Object
*obj
= (Object
*)value
;
316 MyRootInfo
*ri
= (MyRootInfo
*)user_data
;
323 /* fires if you have messed up the hash keys,
324 * e.g. by using non permanent memory */
325 g_assert (0 == strcmp (obj
->type
->name
, name
));
327 p
= strstr (name
, " - ");
329 layer_name
= g_strndup (name
, p
- name
);
331 layer_name
= g_strdup ("default");
333 li
= g_hash_table_lookup (ri
->layer_hash
, layer_name
);
336 li
= g_new (MyLayerInfo
, 1);
337 li
->node
= xmlNewChild(ri
->node
, ri
->name_space
, "layer", NULL
);
338 xmlSetProp(li
->node
, "name", layer_name
);
339 xmlSetProp(li
->node
, "visible", "false");
340 li
->pos
.x
= li
->pos
.y
= 0.0;
341 g_hash_table_insert (ri
->layer_hash
, layer_name
, li
);
344 obj_node
= xmlNewChild(li
->node
, NULL
, "object", NULL
);
345 xmlSetProp(obj_node
, "type", obj
->type
->name
);
347 g_snprintf(buffer
, 30, "%d", obj
->type
->version
);
348 xmlSetProp(obj_node
, "version", buffer
);
350 g_snprintf(buffer
, 30, "O%d", ri
->obj_nr
++);
351 xmlSetProp(obj_node
, "id", buffer
);
353 obj
->ops
->move (obj
,&(li
->pos
));
354 obj
->type
->ops
->save (obj
, obj_node
, ri
->filename
);
355 /* arrange following objects below */
356 li
->pos
.y
+= (obj
->bounding_box
.bottom
- obj
->bounding_box
.top
+ 1.0);
362 * dia_object_defaults_save:
364 * Saves all the currently created default objects into a
365 * valid diagram file. All the objects are placed into
366 * separate invisible layers.
369 dia_object_defaults_save (const gchar
*filename
)
374 gchar
*real_filename
;
375 int old_blanks_default
= pretty_formated_xml
;
377 /* FIXME HACK: we always want nice readable default files,
378 * but toggling it by a global var is ugly --hb
380 pretty_formated_xml
= TRUE
;
383 real_filename
= dia_config_filename("defaults.dia");
385 real_filename
= g_strdup (filename
);
387 doc
= xmlNewDoc("1.0");
388 doc
->encoding
= xmlStrdup("UTF-8");
389 doc
->xmlRootNode
= xmlNewDocNode(doc
, NULL
, "diagram", NULL
);
391 ni
.name_space
= xmlNewNs(doc
->xmlRootNode
,
392 "http://www.lysator.liu.se/~alla/dia/",
394 xmlSetNs(doc
->xmlRootNode
, ni
.name_space
);
397 ni
.node
= doc
->xmlRootNode
;
398 ni
.filename
= real_filename
;
399 ni
.layer_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
402 g_hash_table_foreach (defaults_hash
, _obj_store
, &ni
);
404 ret
= xmlDiaSaveFile (real_filename
, doc
);
405 g_free (real_filename
);
407 pretty_formated_xml
= old_blanks_default
;
409 g_hash_table_destroy (ni
.layer_hash
);