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.
19 /*! \file connection.c -- This file handles simple (straight-line) connection basics */
23 #include <string.h> /* memcpy() */
26 #include "connection.h"
29 /** Adjust connection endings for autogap. This function actually moves the
30 * ends of the connection, but only when the end is connected to
34 connection_adjust_for_autogap(Connection
*connection
)
37 ConnectionPoint
*start_cp
, *end_cp
;
39 start_cp
= connection
->endpoint_handles
[0].connected_to
;
40 end_cp
= connection
->endpoint_handles
[1].connected_to
;
42 endpoints
[0] = connection
->endpoints
[0];
43 endpoints
[1] = connection
->endpoints
[1];
45 if (connpoint_is_autogap(start_cp
)) {
46 endpoints
[0] = start_cp
->pos
;
48 if (connpoint_is_autogap(end_cp
)) {
49 endpoints
[1] = end_cp
->pos
;
52 if (connpoint_is_autogap(start_cp
)) {
53 connection
->endpoints
[0] = calculate_object_edge(&endpoints
[0],
57 if (connpoint_is_autogap(end_cp
)) {
58 connection
->endpoints
[1] = calculate_object_edge(&endpoints
[1],
64 /** Function called to move one of the handles associated with the
66 * This is an object_ops function.
67 * @param obj The object whose handle is being moved.
68 * @param handle The handle being moved.
69 * @param pos The position it has been moved to (corrected for
70 * vertical/horizontal only movement).
71 * @param cp If non-NULL, the connectionpoint found at this position.
72 * If @a cp is NULL, there may or may not be a connectionpoint.
73 * @param The reason the handle was moved.
74 * - HANDLE_MOVE_USER means the user is dragging the point.
75 * - HANDLE_MOVE_USER_FINAL means the user let go of the point.
76 * - HANDLE_MOVE_CONNECTED means it was moved because something
77 * it was connected to moved.
78 * @param modifiers gives a bitset of modifier keys currently held down
79 * - MODIFIER_SHIFT is either shift key
80 * - MODIFIER_ALT is either alt key
81 * - MODIFIER_CONTROL is either control key
82 * Each has MODIFIER_LEFT_* and MODIFIER_RIGHT_* variants
83 * @return An @a ObjectChange* with additional undo information, or
84 * (in most cases) NULL. Undo for moving the handle itself is handled
88 connection_move_handle(Connection
*conn
, HandleId id
,
89 Point
*to
, ConnectionPoint
*cp
,
90 HandleMoveReason reason
, ModifierKeys modifiers
)
93 case HANDLE_MOVE_STARTPOINT
:
94 conn
->endpoints
[0] = *to
;
96 case HANDLE_MOVE_ENDPOINT
:
97 conn
->endpoints
[1] = *to
;
100 message_error("Internal error in connection_move_handle.\n");
106 /** Update the type and placement of the two handles.
107 * This only updates handles 0 and 1, not any handles added by subclasses.
108 * @param conn The connection object to do the update on.
111 connection_update_handles(Connection
*conn
)
113 conn
->endpoint_handles
[0].id
= HANDLE_MOVE_STARTPOINT
;
114 conn
->endpoint_handles
[0].pos
= conn
->endpoints
[0];
116 conn
->endpoint_handles
[1].id
= HANDLE_MOVE_ENDPOINT
;
117 conn
->endpoint_handles
[1].pos
= conn
->endpoints
[1];
120 /** Update the bounding box for a connection.
121 * @param conn The connection to update bounding box on.
124 connection_update_boundingbox(Connection
*conn
)
126 assert(conn
!= NULL
);
128 line_bbox(&conn
->endpoints
[0],&conn
->endpoints
[1],
129 &conn
->extra_spacing
,&conn
->object
.bounding_box
);
132 /** Initialize a connection objects.
133 * This will in turn call object_init.
134 * @param conn A newly allocated connection object.
135 * @param num_handles How many handles to allocate room for.
136 * @param num_connections How many connectionpoints to allocate room for.
139 connection_init(Connection
*conn
, int num_handles
, int num_connections
)
146 assert(num_handles
>=2);
148 object_init(obj
, num_handles
, num_connections
);
150 assert(obj
->handles
!=NULL
);
153 obj
->handles
[i
] = &conn
->endpoint_handles
[i
];
154 obj
->handles
[i
]->type
= HANDLE_MAJOR_CONTROL
;
155 obj
->handles
[i
]->connect_type
= HANDLE_CONNECTABLE
;
156 obj
->handles
[i
]->connected_to
= NULL
;
160 /** Copies an object connection-level and down.
161 * @param from The object to copy from.
162 * @param to The newly allocated object to copy into.
165 connection_copy(Connection
*from
, Connection
*to
)
172 fromobj
= &from
->object
;
174 object_copy(fromobj
, toobj
);
177 to
->endpoints
[i
] = from
->endpoints
[i
];
182 to
->endpoint_handles
[i
] = from
->endpoint_handles
[i
];
183 to
->endpoint_handles
[i
].connected_to
= NULL
;
184 toobj
->handles
[i
] = &to
->endpoint_handles
[i
];
186 memcpy(&to
->extra_spacing
,&from
->extra_spacing
,sizeof(to
->extra_spacing
));
189 /** Function called before an object is deleted.
190 * This function must call the parent class's DestroyFunc, and then free
191 * the memory associated with the object, but not the object itself
192 * Must also unconnect itself from all other objects, which can be done
193 * by calling object_destroy, or letting the super-class call it)
194 * This is one of the object_ops functions.
195 * @param conn An object to destroy.
198 connection_destroy(Connection
*conn
)
200 object_destroy(&conn
->object
);
203 /** Save a connections data to XML.
204 * @param conn The connection to save.
205 * @param obj_node The XML node to save it to.
208 connection_save(Connection
*conn
, ObjectNode obj_node
)
212 object_save(&conn
->object
, obj_node
);
214 attr
= new_attribute(obj_node
, "conn_endpoints");
215 data_add_point(attr
, &conn
->endpoints
[0]);
216 data_add_point(attr
, &conn
->endpoints
[1]);
219 /** Load a connections data from XML.
220 * @param conn A fresh connection object to load into.
221 * @param obj_node The XML node to load from.
224 connection_load(Connection
*conn
, ObjectNode obj_node
)
229 object_load(&conn
->object
, obj_node
);
231 attr
= object_find_attribute(obj_node
, "conn_endpoints");
233 data
= attribute_first_data(attr
);
234 data_point( data
, &conn
->endpoints
[0] );
235 data
= data_next(data
);
236 data_point( data
, &conn
->endpoints
[1] );