2006-12-03 Dimitris Glezos <dimitris@glezos.com>
[dia.git] / objects / flowchart / parallelogram.c
blobe20eb2ead574db52e02e280a36c0581f3df357ea
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/pgram.xpm"
44 /* used when resizing to decide which side of the shape to expand/shrink */
45 typedef enum {
46 ANCHOR_MIDDLE,
47 ANCHOR_START,
48 ANCHOR_END
49 } AnchorShape;
51 #define DEFAULT_WIDTH 2.0
52 #define DEFAULT_HEIGHT 1.0
53 #define DEFAULT_BORDER 0.25
55 #define NUM_CONNECTIONS 17
57 typedef struct _Pgram Pgram;
59 struct _Pgram {
60 Element element;
62 ConnectionPoint connections[NUM_CONNECTIONS];
63 real border_width;
64 Color border_color;
65 Color inner_color;
66 gboolean show_background;
67 LineStyle line_style;
68 real dashlength;
69 real shear_angle, shear_grad;
71 Text *text;
72 TextAttributes attrs;
73 real padding;
76 typedef struct _PgramProperties {
77 gboolean show_background;
78 real shear_angle;
79 real padding;
80 } PgramProperties;
82 static PgramProperties default_properties;
84 static real pgram_distance_from(Pgram *pgram, Point *point);
85 static void pgram_select(Pgram *pgram, Point *clicked_point,
86 DiaRenderer *interactive_renderer);
87 static ObjectChange* pgram_move_handle(Pgram *pgram, Handle *handle,
88 Point *to, ConnectionPoint *cp,
89 HandleMoveReason reason,
90 ModifierKeys modifiers);
91 static ObjectChange* pgram_move(Pgram *pgram, Point *to);
92 static void pgram_draw(Pgram *pgram, DiaRenderer *renderer);
93 static void pgram_update_data(Pgram *pgram, AnchorShape h, AnchorShape v);
94 static DiaObject *pgram_create(Point *startpoint,
95 void *user_data,
96 Handle **handle1,
97 Handle **handle2);
98 static void pgram_destroy(Pgram *pgram);
100 static PropDescription *pgram_describe_props(Pgram *pgram);
101 static void pgram_get_props(Pgram *pgram, GPtrArray *props);
102 static void pgram_set_props(Pgram *pgram, GPtrArray *props);
104 static void pgram_save(Pgram *pgram, ObjectNode obj_node, const char *filename);
105 static DiaObject *pgram_load(ObjectNode obj_node, int version, const char *filename);
107 static ObjectTypeOps pgram_type_ops =
109 (CreateFunc) pgram_create,
110 (LoadFunc) pgram_load,
111 (SaveFunc) pgram_save,
112 (GetDefaultsFunc) NULL,
113 (ApplyDefaultsFunc) NULL
116 DiaObjectType pgram_type =
118 "Flowchart - Parallelogram", /* name */
119 0, /* version */
120 (char **) pgram_xpm, /* pixmap */
122 &pgram_type_ops /* ops */
125 static ObjectOps pgram_ops = {
126 (DestroyFunc) pgram_destroy,
127 (DrawFunc) pgram_draw,
128 (DistanceFunc) pgram_distance_from,
129 (SelectFunc) pgram_select,
130 (CopyFunc) object_copy_using_properties,
131 (MoveFunc) pgram_move,
132 (MoveHandleFunc) pgram_move_handle,
133 (GetPropertiesFunc) object_create_props_dialog,
134 (ApplyPropertiesFunc) object_apply_props_from_dialog,
135 (ObjectMenuFunc) NULL,
136 (DescribePropsFunc) pgram_describe_props,
137 (GetPropsFunc) pgram_get_props,
138 (SetPropsFunc) pgram_set_props,
141 static PropNumData text_padding_data = { 0.0, 10.0, 0.1 };
142 static PropNumData shear_angle_data = { 45.0, 135.0, 1.0 };
144 static PropDescription pgram_props[] = {
145 ELEMENT_COMMON_PROPERTIES,
146 PROP_STD_LINE_WIDTH,
147 PROP_STD_LINE_COLOUR,
148 PROP_STD_FILL_COLOUR,
149 PROP_STD_SHOW_BACKGROUND,
150 PROP_STD_LINE_STYLE,
151 { "shear_angle", PROP_TYPE_REAL, PROP_FLAG_VISIBLE,
152 N_("Shear angle"), NULL, &shear_angle_data },
153 { "padding", PROP_TYPE_REAL, PROP_FLAG_VISIBLE,
154 N_("Text padding"), NULL, &text_padding_data },
155 PROP_STD_TEXT_FONT,
156 PROP_STD_TEXT_HEIGHT,
157 PROP_STD_TEXT_COLOUR,
158 PROP_STD_TEXT_ALIGNMENT,
159 PROP_STD_SAVED_TEXT,
161 { NULL, 0, 0, NULL, NULL, NULL, 0}
164 static PropDescription *
165 pgram_describe_props(Pgram *pgram)
167 if (pgram_props[0].quark == 0)
168 prop_desc_list_calculate_quarks(pgram_props);
169 return pgram_props;
172 static PropOffset pgram_offsets[] = {
173 ELEMENT_COMMON_PROPERTIES_OFFSETS,
174 { "line_width", PROP_TYPE_REAL, offsetof(Pgram, border_width) },
175 { "line_colour", PROP_TYPE_COLOUR, offsetof(Pgram, border_color) },
176 { "fill_colour", PROP_TYPE_COLOUR, offsetof(Pgram, inner_color) },
177 { "show_background", PROP_TYPE_BOOL, offsetof(Pgram, show_background) },
178 { "line_style", PROP_TYPE_LINESTYLE,
179 offsetof(Pgram, line_style), offsetof(Pgram, dashlength) },
180 { "shear_angle", PROP_TYPE_REAL, offsetof(Pgram, shear_angle) },
181 { "padding", PROP_TYPE_REAL, offsetof(Pgram, padding) },
182 {"text",PROP_TYPE_TEXT,offsetof(Pgram,text)},
183 {"text_font",PROP_TYPE_FONT,offsetof(Pgram,attrs.font)},
184 {"text_height",PROP_TYPE_REAL,offsetof(Pgram,attrs.height)},
185 {"text_colour",PROP_TYPE_COLOUR,offsetof(Pgram,attrs.color)},
186 {"text_alignment",PROP_TYPE_ENUM,offsetof(Pgram,attrs.alignment)},
187 { NULL, 0, 0 },
190 static void
191 pgram_get_props(Pgram *pgram, GPtrArray *props)
193 text_get_attributes(pgram->text,&pgram->attrs);
194 object_get_props_from_offsets(&pgram->element.object,
195 pgram_offsets,props);
198 static void
199 pgram_set_props(Pgram *pgram, GPtrArray *props)
201 object_set_props_from_offsets(&pgram->element.object,
202 pgram_offsets,props);
203 apply_textattr_properties(props,pgram->text,"text",&pgram->attrs);
204 pgram_update_data(pgram, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
207 static void
208 init_default_values() {
209 static int defaults_initialized = 0;
211 if (!defaults_initialized) {
212 default_properties.show_background = 1;
213 default_properties.shear_angle = 70.0;
214 default_properties.padding = 0.5;
215 defaults_initialized = 1;
219 static real
220 pgram_distance_from(Pgram *pgram, Point *point)
222 Element *elem = &pgram->element;
223 Rectangle rect;
225 rect.left = elem->corner.x - pgram->border_width/2;
226 rect.right = elem->corner.x + elem->width + pgram->border_width/2;
227 rect.top = elem->corner.y - pgram->border_width/2;
228 rect.bottom = elem->corner.y + elem->height + pgram->border_width/2;
230 /* we do some fiddling with the left/right values to get good accuracy
231 * without having to write a new distance checking routine */
232 if (rect.top > point->y) {
233 /* point above parallelogram */
234 if (pgram->shear_grad > 0)
235 rect.left += pgram->shear_grad * (rect.bottom - rect.top);
236 else
237 rect.right += pgram->shear_grad * (rect.bottom - rect.top);
238 } else if (rect.bottom < point->y) {
239 /* point below parallelogram */
240 if (pgram->shear_grad > 0)
241 rect.right -= pgram->shear_grad * (rect.bottom - rect.top);
242 else
243 rect.left -= pgram->shear_grad * (rect.bottom - rect.top);
244 } else {
245 /* point withing vertical interval of parallelogram -- modify
246 * left and right sides to `unshear' the parallelogram. This
247 * increases accuracy for points near the */
248 if (pgram->shear_grad > 0) {
249 rect.left += pgram->shear_grad * (rect.bottom - point->y);
250 rect.right -= pgram->shear_grad * (point->y - rect.top);
251 } else {
252 rect.left -= pgram->shear_grad * (point->y - rect.top);
253 rect.right += pgram->shear_grad * (rect.bottom - point->y);
257 return distance_rectangle_point(&rect, point);
260 static void
261 pgram_select(Pgram *pgram, Point *clicked_point,
262 DiaRenderer *interactive_renderer)
264 text_set_cursor(pgram->text, clicked_point, interactive_renderer);
265 text_grab_focus(pgram->text, &pgram->element.object);
267 element_update_handles(&pgram->element);
270 static ObjectChange*
271 pgram_move_handle(Pgram *pgram, Handle *handle,
272 Point *to, ConnectionPoint *cp,
273 HandleMoveReason reason, ModifierKeys modifiers)
275 AnchorShape horiz = ANCHOR_MIDDLE, vert = ANCHOR_MIDDLE;
277 assert(pgram!=NULL);
278 assert(handle!=NULL);
279 assert(to!=NULL);
281 element_move_handle(&pgram->element, handle->id, to, cp, reason, modifiers);
283 switch (handle->id) {
284 case HANDLE_RESIZE_NW:
285 horiz = ANCHOR_END; vert = ANCHOR_END; break;
286 case HANDLE_RESIZE_N:
287 vert = ANCHOR_END; break;
288 case HANDLE_RESIZE_NE:
289 horiz = ANCHOR_START; vert = ANCHOR_END; break;
290 case HANDLE_RESIZE_E:
291 horiz = ANCHOR_START; break;
292 case HANDLE_RESIZE_SE:
293 horiz = ANCHOR_START; vert = ANCHOR_START; break;
294 case HANDLE_RESIZE_S:
295 vert = ANCHOR_START; break;
296 case HANDLE_RESIZE_SW:
297 horiz = ANCHOR_END; vert = ANCHOR_START; break;
298 case HANDLE_RESIZE_W:
299 horiz = ANCHOR_END; break;
300 default:
301 break;
303 pgram_update_data(pgram, horiz, vert);
305 return NULL;
308 static ObjectChange*
309 pgram_move(Pgram *pgram, Point *to)
311 pgram->element.corner = *to;
313 pgram_update_data(pgram, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
315 return NULL;
318 static void
319 pgram_draw(Pgram *pgram, DiaRenderer *renderer)
321 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
322 Point pts[4];
323 Element *elem;
324 real offs;
326 assert(pgram != NULL);
327 assert(renderer != NULL);
329 elem = &pgram->element;
331 pts[0] = pts[1] = pts[2] = pts[3] = elem->corner;
332 pts[1].x += elem->width;
333 pts[2].x += elem->width;
334 pts[2].y += elem->height;
335 pts[3].y += elem->height;
337 offs = elem->height * pgram->shear_grad;
338 if (offs > 0) {
339 pts[0].x += offs;
340 pts[2].x -= offs;
341 } else {
342 pts[1].x += offs;
343 pts[3].x -= offs;
346 if (pgram->show_background) {
347 renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID);
349 renderer_ops->fill_polygon(renderer,
350 pts, 4,
351 &pgram->inner_color);
354 renderer_ops->set_linewidth(renderer, pgram->border_width);
355 renderer_ops->set_linestyle(renderer, pgram->line_style);
356 renderer_ops->set_dashlength(renderer, pgram->dashlength);
357 renderer_ops->set_linejoin(renderer, LINEJOIN_MITER);
359 renderer_ops->draw_polygon(renderer,
360 pts, 4,
361 &pgram->border_color);
363 text_draw(pgram->text, renderer);
367 static void
368 pgram_update_data(Pgram *pgram, AnchorShape horiz, AnchorShape vert)
370 Element *elem = &pgram->element;
371 ElementBBExtras *extra = &elem->extra_spacing;
372 DiaObject *obj = &elem->object;
373 Point center, bottom_right;
374 Point p;
375 real offs;
376 real width, height;
377 real avail_width;
378 real top_left;
380 /* save starting points */
381 center = bottom_right = elem->corner;
382 center.x += elem->width/2;
383 bottom_right.x += elem->width;
384 center.y += elem->height/2;
385 bottom_right.y += elem->height;
387 /* this takes the shearing of the parallelogram into account, so the
388 * text can be extend to the edges of the parallelogram */
389 text_calc_boundingbox(pgram->text, NULL);
390 height = pgram->text->height * pgram->text->numlines + pgram->padding*2 +
391 pgram->border_width;
392 if (height > elem->height) elem->height = height;
394 avail_width = elem->width - (pgram->padding*2 + pgram->border_width +
395 fabs(pgram->shear_grad) * (elem->height + pgram->text->height
396 * pgram->text->numlines));
397 if (avail_width < pgram->text->max_width) {
398 elem->width = (elem->width-avail_width) + pgram->text->max_width;
399 avail_width = pgram->text->max_width;
403 width = pgram->text->max_width + pgram->padding*2 + pgram->border_width +
404 fabs(pgram->shear_grad) * (elem->height + pgram->text->height
405 * pgram->text->numlines);
406 if (width > elem->width) elem->width = width;
409 /* move shape if necessary ... */
410 switch (horiz) {
411 case ANCHOR_MIDDLE:
412 elem->corner.x = center.x - elem->width/2; break;
413 case ANCHOR_END:
414 elem->corner.x = bottom_right.x - elem->width; break;
415 default:
416 break;
418 switch (vert) {
419 case ANCHOR_MIDDLE:
420 elem->corner.y = center.y - elem->height/2; break;
421 case ANCHOR_END:
422 elem->corner.y = bottom_right.y - elem->height; break;
423 default:
424 break;
427 p = elem->corner;
428 p.x += elem->width / 2.0;
429 p.y += elem->height / 2.0 - pgram->text->height * pgram->text->numlines / 2 +
430 pgram->text->ascent;
431 switch (pgram->text->alignment) {
432 case ALIGN_LEFT:
433 p.x -= avail_width/2;
434 break;
435 case ALIGN_RIGHT:
436 p.x += avail_width/2;
437 break;
438 case ALIGN_CENTER:
439 break;
441 text_set_position(pgram->text, &p);
443 /* 1/4 of how much more to the left the bottom line is */
444 offs = -(elem->height / 4.0 * pgram->shear_grad);
445 width = elem->width - 4.0*fabs(offs);
446 top_left = elem->corner.x;
447 if (offs < 0.0) {
448 top_left -= 4*offs;
451 /* Update connections: */
452 connpoint_update(&pgram->connections[0],
453 top_left,
454 elem->corner.y,
455 DIR_NORTHWEST);
456 connpoint_update(&pgram->connections[1],
457 top_left + width / 4.0,
458 elem->corner.y,
459 DIR_NORTH);
460 connpoint_update(&pgram->connections[2],
461 top_left + width / 2.0,
462 elem->corner.y,
463 DIR_NORTH);
464 connpoint_update(&pgram->connections[3],
465 top_left + width * 3.0 / 4.0,
466 elem->corner.y,
467 DIR_NORTH);
468 connpoint_update(&pgram->connections[4],
469 top_left + width,
470 elem->corner.y,
471 DIR_NORTHEAST);
472 connpoint_update(&pgram->connections[5],
473 top_left + offs,
474 elem->corner.y + elem->height / 4.0,
475 DIR_WEST);
476 connpoint_update(&pgram->connections[6],
477 top_left + width + offs,
478 elem->corner.y + elem->height / 4.0,
479 DIR_EAST);
480 connpoint_update(&pgram->connections[7],
481 top_left + 2.0 * offs,
482 elem->corner.y + elem->height / 2.0,
483 DIR_WEST);
484 connpoint_update(&pgram->connections[8],
485 top_left + width + 2.0 * offs,
486 elem->corner.y + elem->height / 2.0,
487 DIR_WEST);
488 connpoint_update(&pgram->connections[9],
489 top_left + 3.0 * offs,
490 elem->corner.y + elem->height * 3.0 / 4.0,
491 DIR_WEST);
492 connpoint_update(&pgram->connections[10],
493 top_left + width + 3.0 * offs,
494 elem->corner.y + elem->height * 3.0 / 4.0,
495 DIR_EAST);
496 connpoint_update(&pgram->connections[11],
497 top_left + 4.0 * offs,
498 elem->corner.y + elem->height,
499 DIR_SOUTHWEST);
500 connpoint_update(&pgram->connections[12],
501 top_left + 4.0 * offs + width / 4.0,
502 elem->corner.y + elem->height,
503 DIR_SOUTH);
504 connpoint_update(&pgram->connections[13],
505 top_left + 4.0 * offs + width / 2.0,
506 elem->corner.y + elem->height,
507 DIR_SOUTH);
508 connpoint_update(&pgram->connections[14],
509 top_left + 4.0 * offs + 3.0 * width / 4.0,
510 elem->corner.y + elem->height,
511 DIR_SOUTH);
512 connpoint_update(&pgram->connections[15],
513 top_left + 4.0 * offs + width,
514 elem->corner.y + elem->height,
515 DIR_SOUTHEAST);
516 connpoint_update(&pgram->connections[16],
517 top_left + 2.0 * offs + width / 2,
518 elem->corner.y + elem->height / 2,
519 DIR_ALL);
521 extra->border_trans = pgram->border_width/2.0;
522 element_update_boundingbox(elem);
524 obj->position = elem->corner;
526 element_update_handles(elem);
529 static DiaObject *
530 pgram_create(Point *startpoint,
531 void *user_data,
532 Handle **handle1,
533 Handle **handle2)
535 Pgram *pgram;
536 Element *elem;
537 DiaObject *obj;
538 Point p;
539 int i;
540 DiaFont *font = NULL;
541 real font_height;
543 init_default_values();
545 pgram = g_malloc0(sizeof(Pgram));
546 elem = &pgram->element;
547 obj = &elem->object;
549 obj->type = &pgram_type;
551 obj->ops = &pgram_ops;
553 elem->corner = *startpoint;
554 elem->width = DEFAULT_WIDTH;
555 elem->height = DEFAULT_WIDTH;
557 pgram->border_width = attributes_get_default_linewidth();
558 pgram->border_color = attributes_get_foreground();
559 pgram->inner_color = attributes_get_background();
560 pgram->show_background = default_properties.show_background;
561 attributes_get_default_line_style(&pgram->line_style, &pgram->dashlength);
562 pgram->shear_angle = default_properties.shear_angle;
563 pgram->shear_grad = tan(M_PI/2.0 - M_PI/180.0 * pgram->shear_angle);
565 pgram->padding = default_properties.padding;
567 attributes_get_default_font(&font, &font_height);
568 p = *startpoint;
569 p.x += elem->width / 2.0;
570 p.y += elem->height / 2.0 + font_height / 2;
571 pgram->text = new_text("", font, font_height, &p, &pgram->border_color,
572 ALIGN_CENTER);
573 text_get_attributes(pgram->text,&pgram->attrs);
574 dia_font_unref(font);
576 element_init(elem, 8, NUM_CONNECTIONS);
578 for (i=0;i<NUM_CONNECTIONS;i++) {
579 obj->connections[i] = &pgram->connections[i];
580 pgram->connections[i].object = obj;
581 pgram->connections[i].connected = NULL;
582 pgram->connections[i].flags = 0;
584 pgram->connections[16].flags = CP_FLAGS_MAIN;
586 pgram_update_data(pgram, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
588 *handle1 = NULL;
589 *handle2 = obj->handles[7];
590 return &pgram->element.object;
593 static void
594 pgram_destroy(Pgram *pgram)
596 text_destroy(pgram->text);
598 element_destroy(&pgram->element);
601 static void
602 pgram_save(Pgram *pgram, ObjectNode obj_node, const char *filename)
604 element_save(&pgram->element, obj_node);
606 if (pgram->border_width != 0.1)
607 data_add_real(new_attribute(obj_node, "border_width"),
608 pgram->border_width);
610 if (!color_equals(&pgram->border_color, &color_black))
611 data_add_color(new_attribute(obj_node, "border_color"),
612 &pgram->border_color);
614 if (!color_equals(&pgram->inner_color, &color_white))
615 data_add_color(new_attribute(obj_node, "inner_color"),
616 &pgram->inner_color);
618 data_add_boolean(new_attribute(obj_node, "show_background"), pgram->show_background);
620 if (pgram->line_style != LINESTYLE_SOLID)
621 data_add_enum(new_attribute(obj_node, "line_style"),
622 pgram->line_style);
624 if (pgram->line_style != LINESTYLE_SOLID &&
625 pgram->dashlength != DEFAULT_LINESTYLE_DASHLEN)
626 data_add_real(new_attribute(obj_node, "dashlength"),
627 pgram->dashlength);
629 data_add_real(new_attribute(obj_node, "shear_angle"),
630 pgram->shear_angle);
632 data_add_real(new_attribute(obj_node, "padding"), pgram->padding);
634 data_add_text(new_attribute(obj_node, "text"), pgram->text);
637 static DiaObject *
638 pgram_load(ObjectNode obj_node, int version, const char *filename)
640 Pgram *pgram;
641 Element *elem;
642 DiaObject *obj;
643 int i;
644 AttributeNode attr;
646 pgram = g_malloc0(sizeof(Pgram));
647 elem = &pgram->element;
648 obj = &elem->object;
650 obj->type = &pgram_type;
651 obj->ops = &pgram_ops;
653 element_load(elem, obj_node);
655 pgram->border_width = 0.1;
656 attr = object_find_attribute(obj_node, "border_width");
657 if (attr != NULL)
658 pgram->border_width = data_real( attribute_first_data(attr) );
660 pgram->border_color = color_black;
661 attr = object_find_attribute(obj_node, "border_color");
662 if (attr != NULL)
663 data_color(attribute_first_data(attr), &pgram->border_color);
665 pgram->inner_color = color_white;
666 attr = object_find_attribute(obj_node, "inner_color");
667 if (attr != NULL)
668 data_color(attribute_first_data(attr), &pgram->inner_color);
670 pgram->show_background = TRUE;
671 attr = object_find_attribute(obj_node, "show_background");
672 if (attr != NULL)
673 pgram->show_background = data_boolean( attribute_first_data(attr) );
675 pgram->line_style = LINESTYLE_SOLID;
676 attr = object_find_attribute(obj_node, "line_style");
677 if (attr != NULL)
678 pgram->line_style = data_enum( attribute_first_data(attr) );
680 pgram->dashlength = DEFAULT_LINESTYLE_DASHLEN;
681 attr = object_find_attribute(obj_node, "dashlength");
682 if (attr != NULL)
683 pgram->dashlength = data_real(attribute_first_data(attr));
685 pgram->shear_angle = 0.0;
686 attr = object_find_attribute(obj_node, "shear_angle");
687 if (attr != NULL)
688 pgram->shear_angle = data_real( attribute_first_data(attr) );
689 pgram->shear_grad = tan(M_PI/2.0 - M_PI/180.0 * pgram->shear_angle);
691 pgram->padding = default_properties.padding;
692 attr = object_find_attribute(obj_node, "padding");
693 if (attr != NULL)
694 pgram->padding = data_real( attribute_first_data(attr) );
696 pgram->text = NULL;
697 attr = object_find_attribute(obj_node, "text");
698 if (attr != NULL)
699 pgram->text = data_text(attribute_first_data(attr));
701 element_init(elem, 8, NUM_CONNECTIONS);
703 for (i=0;i<NUM_CONNECTIONS;i++) {
704 obj->connections[i] = &pgram->connections[i];
705 pgram->connections[i].object = obj;
706 pgram->connections[i].connected = NULL;
707 pgram->connections[i].flags = 0;
709 pgram->connections[16].flags = CP_FLAGS_MAIN;
711 pgram_update_data(pgram, ANCHOR_MIDDLE, ANCHOR_MIDDLE);
713 return &pgram->element.object;