2005-12-27 Hans Breuer <hans@breuer.org>
[dia.git] / objects / flowchart / box.c
blobc12c024c3aae39689134468dc9c5554087fa6f53
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * Flowchart toolbox -- objects for drawing flowcharts.
5 * Copyright (C) 1999 James Henstridge.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 /* DO NOT USE THIS OBJECT AS A BASIS FOR A NEW OBJECT. */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <assert.h>
29 #include <math.h>
31 #include "intl.h"
32 #include "object.h"
33 #include "element.h"
34 #include "connectionpoint.h"
35 #include "diarenderer.h"
36 #include "attributes.h"
37 #include "text.h"
38 #include "widgets.h"
39 #include "message.h"
40 #include "properties.h"
42 #include "pixmaps/box.xpm"
44 #define DEFAULT_WIDTH 2.0
45 #define DEFAULT_HEIGHT 1.0
46 #define DEFAULT_BORDER 0.25
48 #define NUM_CONNECTIONS 17
50 typedef enum {
51 ANCHOR_MIDDLE,
52 ANCHOR_START,
53 ANCHOR_END
54 } AnchorShape;
56 typedef struct _Box Box;
58 struct _Box {
59 Element element;
61 ConnectionPoint connections[NUM_CONNECTIONS];
62 real border_width;
63 Color border_color;
64 Color inner_color;
65 gboolean show_background;
66 LineStyle line_style;
67 real dashlength;
68 real corner_radius;
70 Text *text;
71 TextAttributes attrs;
72 real padding;
75 typedef struct _BoxProperties {
76 gboolean show_background;
77 real corner_radius;
78 real padding;
79 } BoxProperties;
81 static BoxProperties default_properties;
83 static real box_distance_from(Box *box, Point *point);
84 static void box_select(Box *box, Point *clicked_point,
85 DiaRenderer *interactive_renderer);
86 static ObjectChange* box_move_handle(Box *box, Handle *handle,
87 Point *to, ConnectionPoint *cp,
88 HandleMoveReason reason,
89 ModifierKeys modifiers);
90 static ObjectChange* box_move(Box *box, Point *to);
91 static void box_draw(Box *box, DiaRenderer *renderer);
92 static void box_update_data(Box *box, AnchorShape horix, AnchorShape vert);
93 static DiaObject *box_create(Point *startpoint,
94 void *user_data,
95 Handle **handle1,
96 Handle **handle2);
97 static void box_destroy(Box *box);
98 static PropDescription *box_describe_props(Box *box);
99 static void box_get_props(Box *box, GPtrArray *props);
100 static void box_set_props(Box *box, GPtrArray *props);
102 static void box_save(Box *box, ObjectNode obj_node, const char *filename);
103 static DiaObject *box_load(ObjectNode obj_node, int version, const char *filename);
105 static ObjectTypeOps box_type_ops =
107 (CreateFunc) box_create,
108 (LoadFunc) box_load,
109 (SaveFunc) box_save,
110 (GetDefaultsFunc) NULL,
111 (ApplyDefaultsFunc) NULL
114 DiaObjectType fc_box_type =
116 "Flowchart - Box", /* name */
117 0, /* version */
118 (char **) box_xpm, /* pixmap */
120 &box_type_ops /* ops */
123 static ObjectOps box_ops = {
124 (DestroyFunc) box_destroy,
125 (DrawFunc) box_draw,
126 (DistanceFunc) box_distance_from,
127 (SelectFunc) box_select,
128 (CopyFunc) object_copy_using_properties,
129 (MoveFunc) box_move,
130 (MoveHandleFunc) box_move_handle,
131 (GetPropertiesFunc) object_create_props_dialog,
132 (ApplyPropertiesFunc) object_apply_props_from_dialog,
133 (ObjectMenuFunc) NULL,
134 (DescribePropsFunc) box_describe_props,
135 (GetPropsFunc) box_get_props,
136 (SetPropsFunc) box_set_props,
139 static PropNumData corner_radius_data = { 0.0, 10.0, 0.1 };
140 static PropNumData text_padding_data = { 0.0, 10.0, 0.1 };
142 static PropDescription box_props[] = {
143 ELEMENT_COMMON_PROPERTIES,
144 PROP_STD_LINE_WIDTH,
145 PROP_STD_LINE_COLOUR,
146 PROP_STD_FILL_COLOUR,
147 PROP_STD_SHOW_BACKGROUND,
148 PROP_STD_LINE_STYLE,
149 { "corner_radius", PROP_TYPE_REAL, PROP_FLAG_VISIBLE,
150 N_("Corner radius"), NULL, &corner_radius_data },
151 { "padding", PROP_TYPE_REAL, PROP_FLAG_VISIBLE,
152 N_("Text padding"), NULL, &text_padding_data },
153 PROP_STD_TEXT_FONT,
154 PROP_STD_TEXT_HEIGHT,
155 PROP_STD_TEXT_COLOUR,
156 PROP_STD_TEXT_ALIGNMENT,
157 PROP_STD_SAVED_TEXT,
159 { NULL, 0, 0, NULL, NULL, NULL, 0}
162 static PropDescription *
163 box_describe_props(Box *box)
165 if (box_props[0].quark == 0)
166 prop_desc_list_calculate_quarks(box_props);
167 return box_props;
170 static PropOffset box_offsets[] = {
171 ELEMENT_COMMON_PROPERTIES_OFFSETS,
172 { "line_width", PROP_TYPE_REAL, offsetof(Box, border_width) },
173 { "line_colour", PROP_TYPE_COLOUR, offsetof(Box, border_color) },
174 { "fill_colour", PROP_TYPE_COLOUR, offsetof(Box, inner_color) },
175 { "show_background", PROP_TYPE_BOOL, offsetof(Box, show_background) },
176 { "line_style", PROP_TYPE_LINESTYLE,
177 offsetof(Box, line_style), offsetof(Box, dashlength) },
178 { "corner_radius", PROP_TYPE_REAL, offsetof(Box, corner_radius) },
179 { "padding", PROP_TYPE_REAL, offsetof(Box, padding) },
180 {"text",PROP_TYPE_TEXT,offsetof(Box,text)},
181 {"text_font",PROP_TYPE_FONT,offsetof(Box,attrs.font)},
182 {"text_height",PROP_TYPE_REAL,offsetof(Box,attrs.height)},
183 {"text_colour",PROP_TYPE_COLOUR,offsetof(Box,attrs.color)},
184 {"text_alignment",PROP_TYPE_ENUM,offsetof(Box,attrs.alignment)},
185 { NULL, 0, 0 },
188 static void
189 box_get_props(Box *box, GPtrArray *props)
191 text_get_attributes(box->text,&box->attrs);
192 object_get_props_from_offsets(&box->element.object,
193 box_offsets,props);
196 static void
197 box_set_props(Box *box, GPtrArray *props)
199 object_set_props_from_offsets(&box->element.object,
200 box_offsets,props);
201 apply_textattr_properties(props,box->text,"text",&box->attrs);
202 box_update_data(box, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
205 static void
206 init_default_values() {
207 static int defaults_initialized = 0;
209 if (!defaults_initialized) {
210 default_properties.show_background = 1;
211 default_properties.padding = 0.5;
212 defaults_initialized = 1;
216 static real
217 box_distance_from(Box *box, Point *point)
219 Element *elem = &box->element;
220 Rectangle rect;
222 rect.left = elem->corner.x - box->border_width/2;
223 rect.right = elem->corner.x + elem->width + box->border_width/2;
224 rect.top = elem->corner.y - box->border_width/2;
225 rect.bottom = elem->corner.y + elem->height + box->border_width/2;
226 return distance_rectangle_point(&rect, point);
229 static void
230 box_select(Box *box, Point *clicked_point,
231 DiaRenderer *interactive_renderer)
233 real radius;
235 text_set_cursor(box->text, clicked_point, interactive_renderer);
236 text_grab_focus(box->text, &box->element.object);
238 element_update_handles(&box->element);
240 if (box->corner_radius > 0) {
241 Element *elem = (Element *)box;
242 radius = box->corner_radius;
243 radius = MIN(radius, elem->width/2);
244 radius = MIN(radius, elem->height/2);
245 radius *= (1-M_SQRT1_2);
247 elem->resize_handles[0].pos.x += radius;
248 elem->resize_handles[0].pos.y += radius;
249 elem->resize_handles[2].pos.x -= radius;
250 elem->resize_handles[2].pos.y += radius;
251 elem->resize_handles[5].pos.x += radius;
252 elem->resize_handles[5].pos.y -= radius;
253 elem->resize_handles[7].pos.x -= radius;
254 elem->resize_handles[7].pos.y -= radius;
258 static ObjectChange*
259 box_move_handle(Box *box, Handle *handle,
260 Point *to, ConnectionPoint *cp,
261 HandleMoveReason reason, ModifierKeys modifiers)
263 AnchorShape horiz = ANCHOR_MIDDLE, vert = ANCHOR_MIDDLE;
265 assert(box!=NULL);
266 assert(handle!=NULL);
267 assert(to!=NULL);
269 element_move_handle(&box->element, handle->id, to, cp, reason, modifiers);
271 switch (handle->id) {
272 case HANDLE_RESIZE_NW:
273 horiz = ANCHOR_END; vert = ANCHOR_END; break;
274 case HANDLE_RESIZE_N:
275 vert = ANCHOR_END; break;
276 case HANDLE_RESIZE_NE:
277 horiz = ANCHOR_START; vert = ANCHOR_END; break;
278 case HANDLE_RESIZE_E:
279 horiz = ANCHOR_START; break;
280 case HANDLE_RESIZE_SE:
281 horiz = ANCHOR_START; vert = ANCHOR_START; break;
282 case HANDLE_RESIZE_S:
283 vert = ANCHOR_START; break;
284 case HANDLE_RESIZE_SW:
285 horiz = ANCHOR_END; vert = ANCHOR_START; break;
286 case HANDLE_RESIZE_W:
287 horiz = ANCHOR_END; break;
288 default:
289 break;
291 box_update_data(box, horiz, vert);
293 return NULL;
296 static ObjectChange*
297 box_move(Box *box, Point *to)
299 box->element.corner = *to;
301 box_update_data(box, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
303 return NULL;
306 static void
307 box_draw(Box *box, DiaRenderer *renderer)
309 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
310 Point lr_corner;
311 Element *elem;
312 real radius;
314 assert(box != NULL);
315 assert(renderer != NULL);
316 elem = &box->element;
318 lr_corner.x = elem->corner.x + elem->width;
319 lr_corner.y = elem->corner.y + elem->height;
321 if (box->show_background) {
322 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
324 /* Problem: How do we make the fill with rounded corners? */
325 if (box->corner_radius > 0) {
326 Point start, end, center;
328 radius = box->corner_radius;
329 radius = MIN(radius, elem->width/2);
330 radius = MIN(radius, elem->height/2);
331 start.x = center.x = elem->corner.x+radius;
332 end.x = lr_corner.x-radius;
333 start.y = elem->corner.y;
334 end.y = lr_corner.y;
335 renderer_ops->fill_rect(renderer, &start, &end, &box->inner_color);
337 center.y = elem->corner.y+radius;
338 renderer_ops->fill_arc(renderer, &center,
339 2.0*radius, 2.0*radius,
340 90.0, 180.0, &box->inner_color);
341 center.x = end.x;
342 renderer_ops->fill_arc(renderer, &center,
343 2.0*radius, 2.0*radius,
344 0.0, 90.0, &box->inner_color);
346 start.x = elem->corner.x;
347 start.y = elem->corner.y+radius;
348 end.x = lr_corner.x;
349 end.y = center.y = lr_corner.y-radius;
350 renderer_ops->fill_rect(renderer, &start, &end, &box->inner_color);
352 center.y = lr_corner.y-radius;
353 center.x = elem->corner.x+radius;
354 renderer_ops->fill_arc(renderer, &center,
355 2.0*radius, 2.0*radius,
356 180.0, 270.0, &box->inner_color);
357 center.x = lr_corner.x-radius;
358 renderer_ops->fill_arc(renderer, &center,
359 2.0*radius, 2.0*radius,
360 270.0, 360.0, &box->inner_color);
361 } else {
362 renderer_ops->fill_rect(renderer,
363 &elem->corner,
364 &lr_corner,
365 &box->inner_color);
369 renderer_ops->set_linewidth(renderer, box->border_width);
370 renderer_ops->set_linestyle(renderer, box->line_style);
371 renderer_ops->set_dashlength(renderer, box->dashlength);
372 renderer_ops->set_linejoin(renderer, LINEJOIN_MITER);
374 if (box->corner_radius > 0) {
375 Point start, end, center;
377 radius = box->corner_radius;
378 radius = MIN(radius, elem->width/2);
379 radius = MIN(radius, elem->height/2);
380 start.x = center.x = elem->corner.x+radius;
381 end.x = lr_corner.x-radius;
382 start.y = end.y = elem->corner.y;
383 renderer_ops->draw_line(renderer, &start, &end, &box->border_color);
384 start.y = end.y = lr_corner.y;
385 renderer_ops->draw_line(renderer, &start, &end, &box->border_color);
387 center.y = elem->corner.y+radius;
388 renderer_ops->draw_arc(renderer, &center,
389 2.0*radius, 2.0*radius,
390 90.0, 180.0, &box->border_color);
391 center.x = end.x;
392 renderer_ops->draw_arc(renderer, &center,
393 2.0*radius, 2.0*radius,
394 0.0, 90.0, &box->border_color);
396 start.y = elem->corner.y+radius;
397 start.x = end.x = elem->corner.x;
398 end.y = center.y = lr_corner.y-radius;
399 renderer_ops->draw_line(renderer, &start, &end, &box->border_color);
400 start.x = end.x = lr_corner.x;
401 renderer_ops->draw_line(renderer, &start, &end, &box->border_color);
403 center.y = lr_corner.y-radius;
404 center.x = elem->corner.x+radius;
405 renderer_ops->draw_arc(renderer, &center,
406 2.0*radius, 2.0*radius,
407 180.0, 270.0, &box->border_color);
408 center.x = lr_corner.x-radius;
409 renderer_ops->draw_arc(renderer, &center,
410 2.0*radius, 2.0*radius,
411 270.0, 360.0, &box->border_color);
412 } else {
413 renderer_ops->draw_rect(renderer,
414 &elem->corner,
415 &lr_corner,
416 &box->border_color);
418 text_draw(box->text, renderer);
421 static void
422 box_update_data(Box *box, AnchorShape horiz, AnchorShape vert)
424 Element *elem = &box->element;
425 ElementBBExtras *extra = &elem->extra_spacing;
426 DiaObject *obj = &elem->object;
427 Point center, bottom_right;
428 Point p;
429 real radius;
430 real width, height;
432 /* save starting points */
433 center = bottom_right = elem->corner;
434 center.x += elem->width/2;
435 bottom_right.x += elem->width;
436 center.y += elem->height/2;
437 bottom_right.y += elem->height;
439 text_calc_boundingbox(box->text, NULL);
440 width = box->text->max_width + box->padding*2 + box->border_width;
441 height = box->text->height * box->text->numlines + box->padding*2 +
442 box->border_width;
445 * If elem->width (e.g. the new requested dimensions of this object
446 * from move_handle()) is smaller than the minimum width (i.e. the
447 * width calculated from text-width, padding and border), then
448 * set the width to the minimum. Else, keep the width.
450 if (width > elem->width) elem->width = width;
451 if (height > elem->height) elem->height = height;
453 /* move shape if necessary ... */
454 switch (horiz) {
455 case ANCHOR_MIDDLE:
456 elem->corner.x = center.x - elem->width/2; break;
457 case ANCHOR_END:
458 elem->corner.x = bottom_right.x - elem->width; break;
459 default:
460 break;
462 switch (vert) {
463 case ANCHOR_MIDDLE:
464 elem->corner.y = center.y - elem->height/2; break;
465 case ANCHOR_END:
466 elem->corner.y = bottom_right.y - elem->height; break;
467 default:
468 break;
471 p = elem->corner;
472 p.x += elem->width / 2.0;
473 p.y += elem->height / 2.0 - box->text->height * box->text->numlines / 2 +
474 box->text->ascent;
475 switch (box->text->alignment) {
476 case ALIGN_LEFT:
477 p.x -= (elem->width - box->padding*2 + box->border_width)/2;
478 break;
479 case ALIGN_RIGHT:
480 p.x += (elem->width - box->padding*2 + box->border_width)/2;
481 break;
482 case ALIGN_CENTER:
483 break;
486 text_set_position(box->text, &p);
488 radius = box->corner_radius;
489 radius = MIN(radius, elem->width/2);
490 radius = MIN(radius, elem->height/2);
491 radius *= (1-M_SQRT1_2);
493 /* Update connections: */
494 connpoint_update(&box->connections[0],
495 elem->corner.x + radius,
496 elem->corner.y + radius,
497 DIR_NORTHWEST);
498 connpoint_update(&box->connections[1],
499 elem->corner.x + elem->width / 4.0,
500 elem->corner.y,
501 DIR_NORTH);
502 connpoint_update(&box->connections[2],
503 elem->corner.x + elem->width / 2.0,
504 elem->corner.y,
505 DIR_NORTH);
506 connpoint_update(&box->connections[3],
507 elem->corner.x + elem->width * 3.0 / 4.0,
508 elem->corner.y,
509 DIR_NORTH);
510 connpoint_update(&box->connections[4],
511 elem->corner.x + elem->width - radius,
512 elem->corner.y + radius,
513 DIR_NORTHEAST);
514 connpoint_update(&box->connections[5],
515 elem->corner.x,
516 elem->corner.y + elem->height / 4.0,
517 DIR_WEST);
518 connpoint_update(&box->connections[6],
519 elem->corner.x + elem->width,
520 elem->corner.y + elem->height / 4.0,
521 DIR_EAST);
522 connpoint_update(&box->connections[7],
523 elem->corner.x,
524 elem->corner.y + elem->height / 2.0,
525 DIR_WEST);
526 connpoint_update(&box->connections[8],
527 elem->corner.x + elem->width,
528 elem->corner.y + elem->height / 2.0,
529 DIR_EAST);
530 connpoint_update(&box->connections[9],
531 elem->corner.x,
532 elem->corner.y + elem->height * 3.0 / 4.0,
533 DIR_WEST);
534 connpoint_update(&box->connections[10],
535 elem->corner.x + elem->width,
536 elem->corner.y + elem->height * 3.0 / 4.0,
537 DIR_EAST);
538 connpoint_update(&box->connections[11],
539 elem->corner.x + radius,
540 elem->corner.y + elem->height - radius,
541 DIR_SOUTHWEST);
542 connpoint_update(&box->connections[12],
543 elem->corner.x + elem->width / 4.0,
544 elem->corner.y + elem->height,
545 DIR_SOUTH);
546 connpoint_update(&box->connections[13],
547 elem->corner.x + elem->width / 2.0,
548 elem->corner.y + elem->height,
549 DIR_SOUTH);
550 connpoint_update(&box->connections[14],
551 elem->corner.x + elem->width * 3.0 / 4.0,
552 elem->corner.y + elem->height,
553 DIR_SOUTH);
554 connpoint_update(&box->connections[15],
555 elem->corner.x + elem->width - radius,
556 elem->corner.y + elem->height - radius,
557 DIR_SOUTHEAST);
558 connpoint_update(&box->connections[16],
559 elem->corner.x + elem->width / 2,
560 elem->corner.y + elem->height / 2,
561 DIR_ALL);
563 extra->border_trans = box->border_width / 2.0;
564 element_update_boundingbox(elem);
566 obj->position = elem->corner;
568 element_update_handles(elem);
570 if (radius > 0.0) {
571 /* Fix the handles, too */
572 elem->resize_handles[0].pos.x += radius;
573 elem->resize_handles[0].pos.y += radius;
574 elem->resize_handles[2].pos.x -= radius;
575 elem->resize_handles[2].pos.y += radius;
576 elem->resize_handles[5].pos.x += radius;
577 elem->resize_handles[5].pos.y -= radius;
578 elem->resize_handles[7].pos.x -= radius;
579 elem->resize_handles[7].pos.y -= radius;
583 static DiaObject *
584 box_create(Point *startpoint,
585 void *user_data,
586 Handle **handle1,
587 Handle **handle2)
589 Box *box;
590 Element *elem;
591 DiaObject *obj;
592 Point p;
593 int i;
594 DiaFont *font = NULL;
595 real font_height;
597 init_default_values();
599 box = g_malloc0(sizeof(Box));
600 elem = &box->element;
601 obj = &elem->object;
603 obj->type = &fc_box_type;
605 obj->ops = &box_ops;
607 elem->corner = *startpoint;
608 elem->width = DEFAULT_WIDTH;
609 elem->height = DEFAULT_HEIGHT;
611 box->border_width = attributes_get_default_linewidth();
612 box->border_color = attributes_get_foreground();
613 box->inner_color = attributes_get_background();
614 box->show_background = default_properties.show_background;
615 attributes_get_default_line_style(&box->line_style, &box->dashlength);
616 box->corner_radius = default_properties.corner_radius;
618 box->padding = default_properties.padding;
620 attributes_get_default_font(&font, &font_height);
621 p = *startpoint;
622 p.x += elem->width / 2.0;
623 p.y += elem->height / 2.0 + font_height / 2;
624 box->text = new_text("", font, font_height, &p, &box->border_color,
625 ALIGN_CENTER);
626 text_get_attributes(box->text,&box->attrs);
627 dia_font_unref(font);
629 element_init(elem, 8, NUM_CONNECTIONS);
631 for (i=0;i<NUM_CONNECTIONS;i++) {
632 obj->connections[i] = &box->connections[i];
633 box->connections[i].object = obj;
634 box->connections[i].connected = NULL;
635 box->connections[i].flags = 0;
637 box->connections[16].flags = CP_FLAGS_MAIN;
639 box_update_data(box, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
641 *handle1 = NULL;
642 *handle2 = obj->handles[7];
643 return &box->element.object;
646 static void
647 box_destroy(Box *box)
649 text_destroy(box->text);
651 element_destroy(&box->element);
654 static void
655 box_save(Box *box, ObjectNode obj_node, const char *filename)
657 element_save(&box->element, obj_node);
659 if (box->border_width != 0.1)
660 data_add_real(new_attribute(obj_node, "border_width"),
661 box->border_width);
663 if (!color_equals(&box->border_color, &color_black))
664 data_add_color(new_attribute(obj_node, "border_color"),
665 &box->border_color);
667 if (!color_equals(&box->inner_color, &color_white))
668 data_add_color(new_attribute(obj_node, "inner_color"),
669 &box->inner_color);
671 data_add_boolean(new_attribute(obj_node, "show_background"),
672 box->show_background);
674 if (box->line_style != LINESTYLE_SOLID)
675 data_add_enum(new_attribute(obj_node, "line_style"),
676 box->line_style);
678 if (box->line_style != LINESTYLE_SOLID &&
679 box->dashlength != DEFAULT_LINESTYLE_DASHLEN)
680 data_add_real(new_attribute(obj_node, "dashlength"),
681 box->dashlength);
682 if (box->corner_radius > 0.0)
683 data_add_real(new_attribute(obj_node, "corner_radius"),
684 box->corner_radius);
686 data_add_real(new_attribute(obj_node, "padding"), box->padding);
688 data_add_text(new_attribute(obj_node, "text"), box->text);
691 static DiaObject *
692 box_load(ObjectNode obj_node, int version, const char *filename)
694 Box *box;
695 Element *elem;
696 DiaObject *obj;
697 int i;
698 AttributeNode attr;
700 box = g_malloc0(sizeof(Box));
701 elem = &box->element;
702 obj = &elem->object;
704 obj->type = &fc_box_type;
705 obj->ops = &box_ops;
707 element_load(elem, obj_node);
709 box->border_width = 0.1;
710 attr = object_find_attribute(obj_node, "border_width");
711 if (attr != NULL)
712 box->border_width = data_real( attribute_first_data(attr) );
713 box->border_color = color_black;
714 attr = object_find_attribute(obj_node, "border_color");
715 if (attr != NULL)
716 data_color(attribute_first_data(attr), &box->border_color);
718 box->inner_color = color_white;
719 attr = object_find_attribute(obj_node, "inner_color");
720 if (attr != NULL)
721 data_color(attribute_first_data(attr), &box->inner_color);
723 box->show_background = TRUE;
724 attr = object_find_attribute(obj_node, "show_background");
725 if (attr != NULL)
726 box->show_background = data_boolean( attribute_first_data(attr) );
728 box->line_style = LINESTYLE_SOLID;
729 attr = object_find_attribute(obj_node, "line_style");
730 if (attr != NULL)
731 box->line_style = data_enum( attribute_first_data(attr) );
733 box->dashlength = DEFAULT_LINESTYLE_DASHLEN;
734 attr = object_find_attribute(obj_node, "dashlength");
735 if (attr != NULL)
736 box->dashlength = data_real(attribute_first_data(attr));
738 box->corner_radius = 0.0;
739 attr = object_find_attribute(obj_node, "corner_radius");
740 if (attr != NULL)
741 box->corner_radius = data_real( attribute_first_data(attr) );
743 box->padding = default_properties.padding;
744 attr = object_find_attribute(obj_node, "padding");
745 if (attr != NULL)
746 box->padding = data_real( attribute_first_data(attr) );
749 box->text = NULL;
750 attr = object_find_attribute(obj_node, "text");
751 if (attr != NULL)
752 box->text = data_text(attribute_first_data(attr));
754 element_init(elem, 8, NUM_CONNECTIONS);
756 for (i=0;i<NUM_CONNECTIONS;i++) {
757 obj->connections[i] = &box->connections[i];
758 box->connections[i].object = obj;
759 box->connections[i].connected = NULL;
760 box->connections[i].flags = 0;
762 box->connections[16].flags = CP_FLAGS_MAIN;
764 box_update_data(box, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
766 return &box->element.object;