* added GDK_PIXBUF_LIBS in order to create pixbuf.dll
[dia.git] / lib / object.c
blob0ecbc0df82c45a3e0c58894c899004871fbcf025
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"
28 #include "dummy_dep.h"
30 void
31 object_init(Object *obj,
32 int num_handles,
33 int num_connections)
35 obj->num_handles = num_handles;
36 if (num_handles>0)
37 obj->handles = g_new0(Handle *,num_handles);
38 else
39 obj->handles = NULL;
41 obj->num_connections = num_connections;
42 if (num_connections>0)
43 obj->connections = g_new0(ConnectionPoint *,num_connections);
44 else
45 obj->connections = NULL;
48 void
49 object_destroy(Object *obj)
51 object_unconnect_all(obj);
53 if (obj->handles)
54 g_free(obj->handles);
56 if (obj->connections)
57 g_free(obj->connections);
62 /* After this copying you have to fix up:
63 handles
64 connections
66 void
67 object_copy(Object *from, Object *to)
69 to->type = from->type;
70 to->position = from->position;
71 to->bounding_box = from->bounding_box;
73 to->num_handles = from->num_handles;
74 if (to->handles != NULL) g_free(to->handles);
75 if (to->num_handles>0)
76 to->handles = g_malloc(sizeof(Handle *)*to->num_handles);
77 else
78 to->handles = NULL;
80 to->num_connections = from->num_connections;
81 if (to->connections != NULL) g_free(to->connections);
82 if (to->num_connections>0)
83 to->connections = g_malloc(sizeof(ConnectionPoint *) * to->num_connections);
84 else
85 to->connections = NULL;
87 to->ops = from->ops;
90 static guint
91 pointer_hash(gpointer some_pointer)
93 return (guint) some_pointer;
96 GList *
97 object_copy_list(GList *list_orig)
99 GList *list_copy;
100 GList *list;
101 Object *obj;
102 Object *obj_copy;
103 GHashTable *hash_table;
104 int i;
106 hash_table = g_hash_table_new((GHashFunc) pointer_hash, NULL);
108 list = list_orig;
109 list_copy = NULL;
110 while (list != NULL) {
111 obj = (Object *)list->data;
112 obj_copy = obj->ops->copy(obj);
114 g_hash_table_insert(hash_table, obj, obj_copy);
116 list_copy = g_list_append(list_copy, obj_copy);
118 list = g_list_next(list);
121 /* Rebuild the connections between the objects in the list: */
122 list = list_orig;
123 while (list != NULL) {
124 obj = (Object *)list->data;
125 obj_copy = g_hash_table_lookup(hash_table, obj);
127 for (i=0;i<obj->num_handles;i++) {
128 ConnectionPoint *con_point;
129 con_point = obj->handles[i]->connected_to;
131 if ( con_point != NULL ) {
132 Object *other_obj;
133 Object *other_obj_copy;
134 int con_point_nr;
136 other_obj = con_point->object;
137 other_obj_copy = g_hash_table_lookup(hash_table, other_obj);
139 if (other_obj_copy == NULL)
140 break; /* other object was not on list. */
142 con_point_nr=0;
143 while (other_obj->connections[con_point_nr] != con_point) {
144 con_point_nr++;
147 object_connect(obj_copy, obj_copy->handles[i],
148 other_obj_copy->connections[con_point_nr]);
152 list = g_list_next(list);
155 g_hash_table_destroy(hash_table);
157 return list_copy;
160 extern void
161 object_list_move_delta(GList *objects, Point *delta)
163 GList *list;
164 Object *obj;
165 Point pos;
167 list = objects;
168 while (list != NULL) {
169 obj = (Object *) list->data;
171 pos = obj->position;
172 point_add(&pos, delta);
174 obj->ops->move(obj, &pos);
176 list = g_list_next(list);
180 void
181 destroy_object_list(GList *list_to_be_destroyed)
183 GList *list;
184 Object *obj;
186 list = list_to_be_destroyed;
187 while (list != NULL) {
188 obj = (Object *)list->data;
190 obj->ops->destroy(obj);
191 g_free(obj);
193 list = g_list_next(list);
196 g_list_free(list_to_be_destroyed);
199 void
200 object_add_handle(Object *obj, Handle *handle)
202 obj->num_handles++;
204 obj->handles =
205 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
207 obj->handles[obj->num_handles-1] = handle;
210 void
211 object_add_handle_at(Object *obj, Handle *handle, int pos)
213 int i;
215 obj->num_handles++;
217 obj->handles =
218 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
220 for (i=obj->num_handles-1; i > pos; i--) {
221 obj->handles[i] = obj->handles[i-1];
223 obj->handles[pos] = handle;
226 void
227 object_remove_handle(Object *obj, Handle *handle)
229 int i, handle_nr;
231 handle_nr = -1;
232 for (i=0;i<obj->num_handles;i++) {
233 if (obj->handles[i] == handle)
234 handle_nr = i;
237 if (handle_nr < 0) {
238 message_error("Internal error, object_remove_handle: Handle doesn't exist");
239 return;
242 for (i=handle_nr;i<(obj->num_handles-1);i++) {
243 obj->handles[i] = obj->handles[i+1];
245 obj->handles[obj->num_handles-1] = NULL;
247 obj->num_handles--;
249 obj->handles =
250 g_realloc(obj->handles, obj->num_handles*sizeof(Handle *));
253 void
254 object_add_connectionpoint(Object *obj, ConnectionPoint *conpoint)
256 obj->num_connections++;
258 obj->connections =
259 g_realloc(obj->connections,
260 obj->num_connections*sizeof(ConnectionPoint *));
262 obj->connections[obj->num_connections-1] = conpoint;
265 void
266 object_add_connectionpoint_at(Object *obj,
267 ConnectionPoint *conpoint, int pos)
269 int i;
271 obj->num_connections++;
273 obj->connections =
274 g_realloc(obj->connections,
275 obj->num_connections*sizeof(ConnectionPoint *));
277 for (i=obj->num_connections-1; i > pos; i--) {
278 obj->connections[i] = obj->connections[i-1];
280 obj->connections[pos] = conpoint;
283 void
284 object_remove_connectionpoint(Object *obj, ConnectionPoint *conpoint)
286 int i, nr;
288 object_remove_connections_to(conpoint);
290 nr = -1;
291 for (i=0;i<obj->num_connections;i++) {
292 if (obj->connections[i] == conpoint)
293 nr = i;
296 if (nr < 0) {
297 message_error("Internal error, object_remove_connectionpoint: "
298 "ConnectionPoint doesn't exist");
299 return;
302 for (i=nr;i<(obj->num_connections-1);i++) {
303 obj->connections[i] = obj->connections[i+1];
305 obj->connections[obj->num_connections-1] = NULL;
307 obj->num_connections--;
309 obj->connections =
310 g_realloc(obj->connections, obj->num_connections*sizeof(ConnectionPoint *));
314 void
315 object_connect(Object *obj, Handle *handle,
316 ConnectionPoint *connectionpoint)
318 if (handle->connect_type==HANDLE_NONCONNECTABLE) {
319 message_error("Error? trying to connect a non connectable handle.\n"
320 "Check this out...\n");
321 return;
323 handle->connected_to = connectionpoint;
324 connectionpoint->connected =
325 g_list_prepend(connectionpoint->connected, obj);
328 void
329 object_unconnect(Object *connected_obj, Handle *handle)
331 ConnectionPoint *connectionpoint;
333 connectionpoint = handle->connected_to;
335 if (connectionpoint!=NULL) {
336 connectionpoint->connected =
337 g_list_remove(connectionpoint->connected, connected_obj);
338 handle->connected_to = NULL;
342 void
343 object_remove_connections_to(ConnectionPoint *conpoint)
345 GList *list;
346 Object *connected_obj;
347 int i;
349 list = conpoint->connected;
350 while (list != NULL) {
351 connected_obj = (Object *)list->data;
353 for (i=0;i<connected_obj->num_handles;i++) {
354 if (connected_obj->handles[i]->connected_to == conpoint) {
355 connected_obj->handles[i]->connected_to = NULL;
358 list = g_list_next(list);
360 g_list_free(conpoint->connected);
361 conpoint->connected = NULL;
364 void
365 object_unconnect_all(Object *obj)
367 int i;
369 for (i=0;i<obj->num_handles;i++) {
370 object_unconnect(obj, obj->handles[i]);
372 for (i=0;i<obj->num_connections;i++) {
373 object_remove_connections_to(obj->connections[i]);
377 void object_save(Object *obj, ObjectNode obj_node)
379 data_add_point(new_attribute(obj_node, "obj_pos"),
380 &obj->position);
381 data_add_rectangle(new_attribute(obj_node, "obj_bb"),
382 &obj->bounding_box);
385 void object_load(Object *obj, ObjectNode obj_node)
387 AttributeNode attr;
389 obj->position.x = 0.0;
390 obj->position.y = 0.0;
391 attr = object_find_attribute(obj_node, "obj_pos");
392 if (attr != NULL)
393 data_point( attribute_first_data(attr), &obj->position );
395 obj->bounding_box.left = obj->bounding_box.right = 0.0;
396 obj->bounding_box.top = obj->bounding_box.bottom = 0.0;
397 attr = object_find_attribute(obj_node, "obj_bb");
398 if (attr != NULL)
399 data_rectangle( attribute_first_data(attr), &obj->bounding_box );
402 Layer *dia_object_get_parent_layer(Object *obj) {
403 return obj->parent_layer;
406 /****** Object register: **********/
408 static guint hash(gpointer key)
410 char *string = (char *)key;
411 int sum;
413 sum = 0;
414 while (*string) {
415 sum += (*string);
416 string++;
419 return sum;
422 static gint compare(gpointer a, gpointer b)
424 return strcmp((char *)a, (char *)b)==0;
427 static GHashTable *object_type_table = NULL;
429 void
430 object_registry_init(void)
432 object_type_table = g_hash_table_new( (GHashFunc) hash, (GCompareFunc) compare );
435 void
436 object_register_type(ObjectType *type)
438 if (g_hash_table_lookup(object_type_table, type->name) != NULL) {
439 message_warning("Several object-types were named %s.\n"
440 "Only first one will be used.\n"
441 "Some things might not work as expected.\n",
442 type->name);
443 return;
445 g_hash_table_insert(object_type_table, type->name, type);
448 void
449 object_registry_foreach (GHFunc func, gpointer user_data)
451 g_hash_table_foreach (object_type_table, func, user_data);
454 ObjectType *
455 object_get_type(char *name)
457 return (ObjectType *) g_hash_table_lookup(object_type_table, name);
462 object_return_false(Object *obj)
464 return FALSE;
467 void *
468 object_return_null(Object *obj)
470 return NULL;
473 void
474 object_return_void(Object *obj)
476 return;
479 Object *
480 object_load_using_properties(const ObjectType *type,
481 ObjectNode obj_node, int version,
482 const char *filename)
484 Object *obj;
485 Point startpoint = {0.0,0.0};
486 Handle *handle1,*handle2;
488 obj = type->ops->create(&startpoint,NULL, &handle1,&handle2);
489 object_load_props(obj,obj_node);
490 return obj;
493 void
494 object_save_using_properties(Object *obj, ObjectNode obj_node,
495 int version, const char *filename)
497 object_save_props(obj,obj_node);
500 Object *object_copy_using_properties(Object *obj)
502 Point startpoint = {0.0,0.0};
503 Handle *handle1,*handle2;
504 Object *newobj = obj->type->ops->create(&startpoint,NULL,
505 &handle1,&handle2);
506 object_copy_props(newobj,obj,FALSE);
507 return newobj;