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.
23 #include <string.h> /* memcpy() */
29 element_update_boundingbox(Element
*elem
) {
32 ElementBBExtras
*extra
= &elem
->extra_spacing
;
36 corner
= &elem
->corner
;
38 bb
.right
= corner
->x
+ elem
->width
;
40 bb
.bottom
= corner
->y
+ elem
->height
;
42 rectangle_bbox(&bb
,extra
,&elem
->object
.bounding_box
);
46 element_update_handles(Element
*elem
)
48 Point
*corner
= &elem
->corner
;
50 elem
->resize_handles
[0].id
= HANDLE_RESIZE_NW
;
51 elem
->resize_handles
[0].pos
.x
= corner
->x
;
52 elem
->resize_handles
[0].pos
.y
= corner
->y
;
54 elem
->resize_handles
[1].id
= HANDLE_RESIZE_N
;
55 elem
->resize_handles
[1].pos
.x
= corner
->x
+ elem
->width
/2.0;
56 elem
->resize_handles
[1].pos
.y
= corner
->y
;
58 elem
->resize_handles
[2].id
= HANDLE_RESIZE_NE
;
59 elem
->resize_handles
[2].pos
.x
= corner
->x
+ elem
->width
;
60 elem
->resize_handles
[2].pos
.y
= corner
->y
;
62 elem
->resize_handles
[3].id
= HANDLE_RESIZE_W
;
63 elem
->resize_handles
[3].pos
.x
= corner
->x
;
64 elem
->resize_handles
[3].pos
.y
= corner
->y
+ elem
->height
/2.0;
66 elem
->resize_handles
[4].id
= HANDLE_RESIZE_E
;
67 elem
->resize_handles
[4].pos
.x
= corner
->x
+ elem
->width
;
68 elem
->resize_handles
[4].pos
.y
= corner
->y
+ elem
->height
/2.0;
70 elem
->resize_handles
[5].id
= HANDLE_RESIZE_SW
;
71 elem
->resize_handles
[5].pos
.x
= corner
->x
;
72 elem
->resize_handles
[5].pos
.y
= corner
->y
+ elem
->height
;
74 elem
->resize_handles
[6].id
= HANDLE_RESIZE_S
;
75 elem
->resize_handles
[6].pos
.x
= corner
->x
+ elem
->width
/2.0;
76 elem
->resize_handles
[6].pos
.y
= corner
->y
+ elem
->height
;
78 elem
->resize_handles
[7].id
= HANDLE_RESIZE_SE
;
79 elem
->resize_handles
[7].pos
.x
= corner
->x
+ elem
->width
;
80 elem
->resize_handles
[7].pos
.y
= corner
->y
+ elem
->height
;
84 element_move_handle(Element
*elem
, HandleId id
,
85 Point
*to
, HandleMoveReason reason
)
90 assert(id
>=HANDLE_RESIZE_NW
);
91 assert(id
<=HANDLE_RESIZE_SE
);
93 corner
= &elem
->corner
;
96 point_sub(&p
, &elem
->corner
);
99 case HANDLE_RESIZE_NW
:
100 if ( to
->x
< (corner
->x
+elem
->width
)) {
104 if ( to
->y
< (corner
->y
+elem
->height
)) {
109 case HANDLE_RESIZE_N
:
110 if ( to
->y
< (corner
->y
+elem
->height
)) {
115 case HANDLE_RESIZE_NE
:
118 if ( to
->y
< (corner
->y
+elem
->height
)) {
123 case HANDLE_RESIZE_W
:
124 if ( to
->x
< (corner
->x
+elem
->width
)) {
129 case HANDLE_RESIZE_E
:
133 case HANDLE_RESIZE_SW
:
134 if ( to
->x
< (corner
->x
+elem
->width
)) {
141 case HANDLE_RESIZE_S
:
145 case HANDLE_RESIZE_SE
:
152 message_error("Error, called element_move_handle() with wrong handle-id\n");
157 element_move_handle_aspect(Element
*elem
, HandleId id
,
158 Point
*to
, real aspect_ratio
)
163 real new_width
, new_height
;
166 assert(id
>=HANDLE_RESIZE_NW
);
167 assert(id
<=HANDLE_RESIZE_SE
);
169 corner
= &elem
->corner
;
172 point_sub(&p
, &elem
->corner
);
175 height
= elem
->height
;
182 case HANDLE_RESIZE_NW
:
183 new_width
= width
- p
.x
;
184 new_height
= height
- p
.y
;
188 case HANDLE_RESIZE_N
:
189 new_height
= height
- p
.y
;
193 case HANDLE_RESIZE_NE
:
195 new_height
= height
- p
.y
;
199 case HANDLE_RESIZE_W
:
200 new_width
= width
- p
.x
;
204 case HANDLE_RESIZE_E
:
209 case HANDLE_RESIZE_SW
:
210 new_width
= width
- p
.x
;
215 case HANDLE_RESIZE_S
:
220 case HANDLE_RESIZE_SE
:
227 message_error("Error, called element_move_handle() with wrong handle-id\n");
230 /* Which of the two versions to use: */
231 if (new_width
> new_height
*aspect_ratio
) {
232 new_height
= new_width
/aspect_ratio
;
234 new_width
= new_height
*aspect_ratio
;
237 if ( (new_width
<0.0) || (new_height
<0.0)) {
242 corner
->x
-= (new_width
- width
)*move_x
;
243 corner
->y
-= (new_height
- height
)*move_y
;
245 elem
->width
= new_width
;
246 elem
->height
= new_height
;
249 /* Needs to have the first 8 handles */
251 element_init(Element
*elem
, int num_handles
, int num_connections
)
258 assert(num_handles
>=8);
260 object_init(obj
, num_handles
, num_connections
);
263 obj
->handles
[i
] = &elem
->resize_handles
[i
];
264 obj
->handles
[i
]->connect_type
= HANDLE_NONCONNECTABLE
;
265 obj
->handles
[i
]->connected_to
= NULL
;
266 obj
->handles
[i
]->type
= HANDLE_MAJOR_CONTROL
;
271 element_copy(Element
*from
, Element
*to
)
273 Object
*toobj
, *fromobj
;
276 fromobj
= &from
->object
;
279 object_copy(fromobj
, toobj
);
281 to
->corner
= from
->corner
;
282 to
->width
= from
->width
;
283 to
->height
= from
->height
;
286 to
->resize_handles
[i
] = from
->resize_handles
[i
];
287 to
->resize_handles
[i
].connected_to
= NULL
;
288 toobj
->handles
[i
] = &to
->resize_handles
[i
];
290 memcpy(&to
->extra_spacing
,&from
->extra_spacing
,sizeof(to
->extra_spacing
));
294 element_destroy(Element
*elem
)
296 object_destroy(&elem
->object
);
300 void element_save(Element
*elem
, ObjectNode obj_node
)
302 object_save(&elem
->object
, obj_node
);
304 data_add_point(new_attribute(obj_node
, "elem_corner"),
306 data_add_real(new_attribute(obj_node
, "elem_width"),
308 data_add_real(new_attribute(obj_node
, "elem_height"),
312 void element_load(Element
*elem
, ObjectNode obj_node
)
316 object_load(&elem
->object
, obj_node
);
318 elem
->corner
.x
= 0.0;
319 elem
->corner
.y
= 0.0;
320 attr
= object_find_attribute(obj_node
, "elem_corner");
322 data_point( attribute_first_data(attr
), &elem
->corner
);
325 attr
= object_find_attribute(obj_node
, "elem_width");
327 elem
->width
= data_real( attribute_first_data(attr
));
330 attr
= object_find_attribute(obj_node
, "elem_height");
332 elem
->height
= data_real( attribute_first_data(attr
));