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 DiaObjectType
*type
= (DiaObjectType
*)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 DiaObject
*obj
= (DiaObject
*)val
;
76 obj
->ops
->destroy (obj
);
80 * @param filename the file to load from or NULL for default
81 * @param create_lazy if FALSE creates default objects for
82 * every known type. Otherwise default objects
83 * are created on demand
85 * Create all the default objects.
88 dia_object_defaults_load (const gchar
*filename
, gboolean create_lazy
)
92 ObjectNode obj_node
, layer_node
;
94 object_default_create_lazy
= create_lazy
;
98 defaults_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
102 object_registry_foreach (_obj_create
, defaults_hash
);
106 /* overload properties from file */
109 gchar
*default_filename
= dia_config_filename("defaults.dia");
111 if (g_file_test(default_filename
, G_FILE_TEST_EXISTS
))
112 doc
= xmlDiaParseFile(default_filename
);
115 g_free (default_filename
);
118 doc
= xmlDiaParseFile(filename
);
123 name_space
= xmlSearchNs(doc
, doc
->xmlRootNode
, "dia");
124 if ( strcmp (doc
->xmlRootNode
->name
, "diagram")
125 || (name_space
== NULL
))
127 message_error(_("Error loading defaults '%s'.\n"
128 "Not a Dia diagram file."),
129 dia_message_filename(filename
));
134 layer_node
= doc
->xmlRootNode
->xmlChildrenNode
;
137 if ( !xmlIsBlankNode(layer_node
)
138 && 0 == strcmp(layer_node
->name
, "layer"))
140 obj_node
= layer_node
->xmlChildrenNode
;
143 if ( !xmlIsBlankNode(obj_node
)
144 && 0 == strcmp(obj_node
->name
, "object"))
146 char *typestr
= xmlGetProp(obj_node
, "type");
147 char *version
= xmlGetProp(obj_node
, "version");
150 DiaObject
*obj
= g_hash_table_lookup (defaults_hash
, typestr
);
154 g_warning ("Unknown object '%s' while reading '%s'",
158 DiaObjectType
*type
= object_get_type (typestr
);
160 obj
= type
->ops
->load (
162 version
? atoi(version
) : 0,
165 g_hash_table_insert (defaults_hash
,
166 obj
->type
->name
, obj
);
171 #if 0 /* lots of complaining about missing attributes */
172 object_load_props(obj
, obj_node
); /* leaks ?? */
175 def_obj
= obj
->type
->ops
->load (
177 version
? atoi(version
) : 0,
179 if (def_obj
->ops
->set_props
)
181 object_copy_props (obj
, def_obj
, TRUE
);
182 def_obj
->ops
->destroy (def_obj
);
186 /* can't copy props */
187 g_hash_table_replace (defaults_hash
,
188 def_obj
->type
->name
, def_obj
);
197 obj_node
= obj_node
->next
;
200 layer_node
= layer_node
->next
;
208 * Remember as defaults from a diagram object
211 dia_object_default_make (const DiaObject
*obj_from
)
215 g_return_if_fail (obj_from
);
217 obj_to
= dia_object_default_get (obj_from
->type
);
218 g_return_if_fail (obj_to
);
220 object_copy_props (obj_to
, obj_from
, TRUE
);
224 * dia_object_default_get :
225 * @param type The type of the object for which you want the defaults object.
227 * Allows to edit one defaults object properties
230 dia_object_default_get (const DiaObjectType
*type
)
234 obj
= g_hash_table_lookup (defaults_hash
, type
->name
);
235 if (!obj
&& object_default_create_lazy
)
237 Point startpoint
= {0.0,0.0};
238 Handle
*handle1
,*handle2
;
240 /* at least 'Group' has no ops */
244 /* the custom objects needs extra_data */
245 obj
= type
->ops
->create(&startpoint
,
246 type
->default_user_data
,
249 g_hash_table_insert (defaults_hash
, obj
->type
->name
, obj
);
256 * dia_object_default_create:
257 * @param type The objects type
258 * @param startpoint The left upper corner
262 * @return A newly created object.
264 * Create an object respecting defaults if available
267 dia_object_default_create (const DiaObjectType
*type
,
273 const DiaObject
*def_obj
;
276 g_return_val_if_fail (type
!= NULL
, NULL
);
278 def_obj
= dia_object_default_get (type
);
279 if (def_obj
&& def_obj
->ops
->describe_props
)
281 /* copy properties to new object, but keep position */
282 obj
= type
->ops
->create (startpoint
, user_data
, handle1
, handle2
);
285 object_copy_props (obj
, def_obj
, TRUE
);
286 obj
->ops
->move (obj
, startpoint
);
291 obj
= type
->ops
->create (startpoint
, user_data
, handle1
, handle2
);
297 typedef struct _MyLayerInfo MyLayerInfo
;
304 typedef struct _MyRootInfo MyRootInfo
;
309 GHashTable
*layer_hash
;
315 _obj_store (gpointer key
,
319 gchar
*name
= (gchar
*)key
;
320 DiaObject
*obj
= (DiaObject
*)value
;
321 MyRootInfo
*ri
= (MyRootInfo
*)user_data
;
328 /* fires if you have messed up the hash keys,
329 * e.g. by using non permanent memory */
330 g_assert (0 == strcmp (obj
->type
->name
, name
));
332 p
= strstr (name
, " - ");
335 layer_name
= g_strndup (name
, p
- name
);
337 layer_name
= g_strdup("NULL");
340 layer_name
= g_strdup ("default");
342 li
= g_hash_table_lookup (ri
->layer_hash
, layer_name
);
345 li
= g_new (MyLayerInfo
, 1);
346 li
->node
= xmlNewChild(ri
->node
, ri
->name_space
, "layer", NULL
);
347 xmlSetProp(li
->node
, "name", layer_name
);
348 xmlSetProp(li
->node
, "visible", "false");
349 li
->pos
.x
= li
->pos
.y
= 0.0;
350 g_hash_table_insert (ri
->layer_hash
, layer_name
, li
);
355 obj_node
= xmlNewChild(li
->node
, NULL
, "object", NULL
);
356 xmlSetProp(obj_node
, "type", obj
->type
->name
);
358 g_snprintf(buffer
, 30, "%d", obj
->type
->version
);
359 xmlSetProp(obj_node
, "version", buffer
);
361 g_snprintf(buffer
, 30, "O%d", ri
->obj_nr
++);
362 xmlSetProp(obj_node
, "id", buffer
);
364 obj
->ops
->move (obj
,&(li
->pos
));
365 obj
->type
->ops
->save (obj
, obj_node
, ri
->filename
);
366 /* arrange following objects below */
367 li
->pos
.y
+= (obj
->bounding_box
.bottom
- obj
->bounding_box
.top
+ 1.0);
371 * dia_object_defaults_save:
373 * Saves all the currently created default objects into a
374 * valid diagram file. All the objects are placed into
375 * separate invisible layers.
378 dia_object_defaults_save (const gchar
*filename
)
383 gchar
*real_filename
;
384 int old_blanks_default
= pretty_formated_xml
;
386 /* FIXME HACK: we always want nice readable default files,
387 * but toggling it by a global var is ugly --hb
389 pretty_formated_xml
= TRUE
;
392 real_filename
= dia_config_filename("defaults.dia");
394 real_filename
= g_strdup (filename
);
396 doc
= xmlNewDoc("1.0");
397 doc
->encoding
= xmlStrdup("UTF-8");
398 doc
->xmlRootNode
= xmlNewDocNode(doc
, NULL
, "diagram", NULL
);
400 ni
.name_space
= xmlNewNs(doc
->xmlRootNode
,
401 DIA_XML_NAME_SPACE_BASE
,
403 xmlSetNs(doc
->xmlRootNode
, ni
.name_space
);
406 ni
.node
= doc
->xmlRootNode
;
407 ni
.filename
= real_filename
;
408 ni
.layer_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
411 g_hash_table_foreach (defaults_hash
, _obj_store
, &ni
);
413 ret
= xmlDiaSaveFile (real_filename
, doc
);
414 g_free (real_filename
);
416 pretty_formated_xml
= old_blanks_default
;
418 g_hash_table_destroy (ni
.layer_hash
);