re-adding .pngs as binary
[dia.git] / lib / object.c
blob343c95edf5bb0d30322661d76be11a8b659b2c95
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
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.
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.
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.
18 #include <config.h>
20 #include <stdio.h>
21 #include <string.h>
23 #include <gtk/gtk.h>
25 #include "object.h"
26 #include "message.h"
27 #include "sheet.h"
29 #include "dummy_dep.h"
31 void
32 object_init(Object *obj,
33 int num_handles,
34 int num_connections)
36 obj->num_handles = num_handles;
37 if (num_handles>0)
38 obj->handles = g_new0(Handle *,num_handles);
39 else
40 obj->handles = NULL;
42 obj->num_connections = num_connections;
43 if (num_connections>0)
44 obj->connections = g_new0(ConnectionPoint *,num_connections);
45 else
46 obj->connections = NULL;
49 void
50 object_destroy(Object *obj)
52 object_unconnect_all(obj);
54 if (obj->handles)
55 g_free(obj->handles);
57 if (obj->connections)
58 g_free(obj->connections);
63 /* After this copying you have to fix up:
64 handles
65 connections
67 void
68 object_copy(Object *from, Object *to)
70 to->type = from->type;
71 to->position = from->position;
72 to->bounding_box = from->bounding_box;
74 to->num_handles = from->num_handles;
75 if (to->handles != NULL) g_free(to->handles);
76 if (to->num_handles>0)
77 to->handles = g_malloc(sizeof(Handle *)*to->num_handles);
78 else
79 to->handles = NULL;
81 to->num_connections = from->num_connections;
82 if (to->connections != NULL) g_free(to->connections);
83 if (to->num_connections>0)
84 to->connections = g_malloc(sizeof(ConnectionPoint *) * to->num_connections);
85 else
86 to->connections = NULL;
88 to->ops = from->ops;
92 void
93 destroy_object_list(GList *list_to_be_destroyed)
95 GList *list;
96 Object *obj;
98 list = list_to_be_destroyed;
99 while (list != NULL) {
100 obj = (Object *)list->data;
102 obj->ops->destroy(obj);
103 g_free(obj);
105 list = g_list_next(list);
108 g_list_free(list_to_be_destroyed);
111 void
112 object_add_handle(Object *obj, Handle *handle)
114 obj->num_handles++;
116 obj->handles =
117 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
119 obj->handles[obj->num_handles-1] = handle;
122 void
123 object_add_handle_at(Object *obj, Handle *handle, int pos)
125 int i;
127 obj->num_handles++;
129 obj->handles =
130 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
132 for (i=obj->num_handles-1; i > pos; i--) {
133 obj->handles[i] = obj->handles[i-1];
135 obj->handles[pos] = handle;
138 void
139 object_remove_handle(Object *obj, Handle *handle)
141 int i, handle_nr;
143 handle_nr = -1;
144 for (i=0;i<obj->num_handles;i++) {
145 if (obj->handles[i] == handle)
146 handle_nr = i;
149 if (handle_nr < 0) {
150 message_error("Internal error, object_remove_handle: Handle doesn't exist");
151 return;
154 for (i=handle_nr;i<(obj->num_handles-1);i++) {
155 obj->handles[i] = obj->handles[i+1];
157 obj->handles[obj->num_handles-1] = NULL;
159 obj->num_handles--;
161 obj->handles =
162 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
165 void
166 object_add_connectionpoint(Object *obj, ConnectionPoint *conpoint)
168 obj->num_connections++;
170 obj->connections =
171 g_realloc(obj->connections,
172 obj->num_connections*sizeof(ConnectionPoint *));
174 obj->connections[obj->num_connections-1] = conpoint;
177 void
178 object_add_connectionpoint_at(Object *obj,
179 ConnectionPoint *conpoint, int pos)
181 int i;
183 obj->num_connections++;
185 obj->connections =
186 g_realloc(obj->connections,
187 obj->num_connections*sizeof(ConnectionPoint *));
189 for (i=obj->num_connections-1; i > pos; i--) {
190 obj->connections[i] = obj->connections[i-1];
192 obj->connections[pos] = conpoint;
195 void
196 object_remove_connectionpoint(Object *obj, ConnectionPoint *conpoint)
198 int i, nr;
200 object_remove_connections_to(conpoint);
202 nr = -1;
203 for (i=0;i<obj->num_connections;i++) {
204 if (obj->connections[i] == conpoint)
205 nr = i;
208 if (nr < 0) {
209 message_error("Internal error, object_remove_connectionpoint: "
210 "ConnectionPoint doesn't exist");
211 return;
214 for (i=nr;i<(obj->num_connections-1);i++) {
215 obj->connections[i] = obj->connections[i+1];
217 obj->connections[obj->num_connections-1] = NULL;
219 obj->num_connections--;
221 obj->connections =
222 g_realloc(obj->connections, obj->num_connections*sizeof(ConnectionPoint *));
226 void
227 object_connect(Object *obj, Handle *handle,
228 ConnectionPoint *connectionpoint)
230 if (handle->connect_type==HANDLE_NONCONNECTABLE) {
231 message_error("Error? trying to connect a non connectable handle.\n"
232 "Check this out...\n");
233 return;
235 handle->connected_to = connectionpoint;
236 connectionpoint->connected =
237 g_list_prepend(connectionpoint->connected, obj);
240 void
241 object_unconnect(Object *connected_obj, Handle *handle)
243 ConnectionPoint *connectionpoint;
245 connectionpoint = handle->connected_to;
247 if (connectionpoint!=NULL) {
248 connectionpoint->connected =
249 g_list_remove(connectionpoint->connected, connected_obj);
250 handle->connected_to = NULL;
254 void
255 object_remove_connections_to(ConnectionPoint *conpoint)
257 GList *list;
258 Object *connected_obj;
259 int i;
261 list = conpoint->connected;
262 while (list != NULL) {
263 connected_obj = (Object *)list->data;
265 for (i=0;i<connected_obj->num_handles;i++) {
266 if (connected_obj->handles[i]->connected_to == conpoint) {
267 connected_obj->handles[i]->connected_to = NULL;
270 list = g_list_next(list);
272 g_list_free(conpoint->connected);
273 conpoint->connected = NULL;
276 void
277 object_unconnect_all(Object *obj)
279 int i;
281 for (i=0;i<obj->num_handles;i++) {
282 object_unconnect(obj, obj->handles[i]);
284 for (i=0;i<obj->num_connections;i++) {
285 object_remove_connections_to(obj->connections[i]);
289 void object_save(Object *obj, ObjectNode obj_node)
291 data_add_point(new_attribute(obj_node, "obj_pos"),
292 &obj->position);
293 data_add_rectangle(new_attribute(obj_node, "obj_bb"),
294 &obj->bounding_box);
297 void object_load(Object *obj, ObjectNode obj_node)
299 AttributeNode attr;
301 obj->position.x = 0.0;
302 obj->position.y = 0.0;
303 attr = object_find_attribute(obj_node, "obj_pos");
304 if (attr != NULL)
305 data_point( attribute_first_data(attr), &obj->position );
307 obj->bounding_box.left = obj->bounding_box.right = 0.0;
308 obj->bounding_box.top = obj->bounding_box.bottom = 0.0;
309 attr = object_find_attribute(obj_node, "obj_bb");
310 if (attr != NULL)
311 data_rectangle( attribute_first_data(attr), &obj->bounding_box );
314 /****** Object register: **********/
316 static guint hash(gpointer key)
318 char *string = (char *)key;
319 int sum;
321 sum = 0;
322 while (*string) {
323 sum += (*string);
324 string++;
327 return sum;
330 static gint compare(gpointer a, gpointer b)
332 return strcmp((char *)a, (char *)b)==0;
335 static GHashTable *object_type_table = NULL;
337 void
338 object_registry_init(void)
340 object_type_table = g_hash_table_new( (GHashFunc) hash, (GCompareFunc) compare );
343 void
344 object_register_type(ObjectType *type)
346 if (g_hash_table_lookup(object_type_table, type->name) != NULL) {
347 message_warning("Several object-types were named %s.\n"
348 "Only first one will be used.\n"
349 "Some things might not work as expected.\n",
350 type->name);
351 return;
353 g_hash_table_insert(object_type_table, type->name, type);
356 static GSList *object_types_nosheet_list = NULL;
358 static void
359 object_type_detect_nosheet_callback(gpointer key, gpointer value,
360 gpointer user_data)
362 GSList *sheets_list;
363 gboolean found = FALSE;
364 gchar *sheet_name;
365 guint i;
366 static gchar *ignore[] = /* Ignore ObjectType's with these */
367 { /* 'name's. Mostly used for object */
368 "Group", /* types that are obsolete and thus */
369 /* are not found on any sheet. */
370 "Contact - if",
371 "Contact - ifnot",
372 "Contact - lamp",
373 "Contact - relay",
374 "GRAFCET - Vector",
375 "UML - Objet",
376 NULL
379 for (i = 0; ignore[i]; i++)
380 if (!strcmp(((ObjectType *)(value))->name, ignore[i]))
381 return;
383 /* We also ignore ObjectType's that begin with 'Standard -' */
385 sheet_name = object_type_get_sheet_name((ObjectType *)value);
386 if (!strcmp(sheet_name, "Standard"))
388 g_free(sheet_name);
389 return;
391 g_free(sheet_name);
393 for (sheets_list = get_sheets_list(); sheets_list && found == FALSE;
394 sheets_list = g_slist_next(sheets_list))
396 GSList *objects_list = ((Sheet *)(sheets_list)->data)->objects;
398 for ( ; objects_list; objects_list = g_slist_next(objects_list))
400 if (!strcmp(key, ((SheetObject *)(objects_list)->data)->object_type))
402 found = TRUE;
403 break;
408 if (found == FALSE)
409 object_types_nosheet_list = g_slist_append(object_types_nosheet_list,
410 g_memdup(value,
411 sizeof(ObjectType)));
414 GSList *
415 object_types_detect_nosheet(void)
417 g_slist_foreach(object_types_nosheet_list, (GFunc)g_free, NULL);
418 g_slist_free(object_types_nosheet_list);
419 g_hash_table_foreach(object_type_table,
420 (GHFunc)object_type_detect_nosheet_callback, NULL);
421 return object_types_nosheet_list;
424 gchar *
425 object_type_get_sheet_name(ObjectType *type)
427 gchar *pos;
428 gchar *sheet_name;
430 sheet_name = g_strdup(type->name);
431 pos = strchr(sheet_name, '-');
432 if (pos)
433 return g_strchomp(g_strdelimit(sheet_name, "-", '\0'));
434 else
435 return sheet_name;
438 gchar *
439 object_type_strip_sheet_from_name(ObjectType *type)
441 gchar *pos;
443 pos = strchr(type->name, '-');
444 if (pos)
445 return pos + 2;
446 else
447 return type->name;
450 ObjectType *
451 object_get_type(char *name)
453 return (ObjectType *) g_hash_table_lookup(object_type_table, name);
458 object_return_false(Object *obj)
460 return FALSE;
463 void *
464 object_return_null(Object *obj)
466 return NULL;
469 void
470 object_return_void(Object *obj)
472 return;
475 Object *
476 object_load_using_properties(const ObjectType *type,
477 ObjectNode obj_node, int version,
478 const char *filename)
480 Object *obj;
481 Point startpoint = {0.0,0.0};
482 Handle *handle1,*handle2;
484 obj = type->ops->create(&startpoint,NULL, &handle1,&handle2);
485 object_load_props(obj,obj_node);
486 return obj;
489 void
490 object_save_using_properties(Object *obj, ObjectNode obj_node,
491 int version, const char *filename)
493 object_save_props(obj,obj_node);
496 Object *object_copy_using_properties(Object *obj)
498 Point startpoint = {0.0,0.0};
499 Handle *handle1,*handle2;
500 Object *newobj = obj->type->ops->create(&startpoint,NULL,
501 &handle1,&handle2);
502 object_copy_props(newobj,obj);
503 return newobj;