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.
29 #include "diarenderer.h"
30 #include "attributes.h"
32 #include "properties.h"
34 #include "pixmaps/actor.xpm"
36 #define NUM_CONNECTIONS 9
38 typedef struct _Actor Actor
;
42 ConnectionPoint connections
[NUM_CONNECTIONS
];
51 #define ACTOR_WIDTH 2.2
52 #define ACTOR_HEIGHT 4.6
53 #define ACTOR_HEAD(h) (h*0.6/4.6)
54 #define ACTOR_BODY(h) (h*4.0/4.6)
55 #define ACTOR_LINEWIDTH 0.1
56 #define ACTOR_MARGIN_X 0.3
57 #define ACTOR_MARGIN_Y 0.3
59 static real
actor_distance_from(Actor
*actor
, Point
*point
);
60 static void actor_select(Actor
*actor
, Point
*clicked_point
,
61 DiaRenderer
*interactive_renderer
);
62 static ObjectChange
* actor_move_handle(Actor
*actor
, Handle
*handle
,
63 Point
*to
, ConnectionPoint
*cp
,
64 HandleMoveReason reason
, ModifierKeys modifiers
);
65 static ObjectChange
* actor_move(Actor
*actor
, Point
*to
);
66 static void actor_draw(Actor
*actor
, DiaRenderer
*renderer
);
67 static DiaObject
*actor_create(Point
*startpoint
,
71 static void actor_destroy(Actor
*actor
);
72 static DiaObject
*actor_load(ObjectNode obj_node
, int version
,
73 const char *filename
);
75 static PropDescription
*actor_describe_props(Actor
*actor
);
76 static void actor_get_props(Actor
*actor
, GPtrArray
*props
);
77 static void actor_set_props(Actor
*actor
, GPtrArray
*props
);
79 static void actor_update_data(Actor
*actor
);
81 static ObjectTypeOps actor_type_ops
=
83 (CreateFunc
) actor_create
,
84 (LoadFunc
) actor_load
,/*using_properties*/ /* load */
85 (SaveFunc
) object_save_using_properties
, /* save */
86 (GetDefaultsFunc
) NULL
,
87 (ApplyDefaultsFunc
) NULL
90 DiaObjectType actor_type
=
92 "UML - Actor", /* name */
94 (char **) actor_xpm
, /* pixmap */
96 &actor_type_ops
/* ops */
99 static ObjectOps actor_ops
= {
100 (DestroyFunc
) actor_destroy
,
101 (DrawFunc
) actor_draw
,
102 (DistanceFunc
) actor_distance_from
,
103 (SelectFunc
) actor_select
,
104 (CopyFunc
) object_copy_using_properties
,
105 (MoveFunc
) actor_move
,
106 (MoveHandleFunc
) actor_move_handle
,
107 (GetPropertiesFunc
) object_create_props_dialog
,
108 (ApplyPropertiesFunc
) object_apply_props_from_dialog
,
109 (ObjectMenuFunc
) NULL
,
110 (DescribePropsFunc
) actor_describe_props
,
111 (GetPropsFunc
) actor_get_props
,
112 (SetPropsFunc
) actor_set_props
,
115 static PropDescription actor_props
[] = {
116 ELEMENT_COMMON_PROPERTIES
,
118 PROP_STD_TEXT_HEIGHT
,
119 PROP_STD_TEXT_COLOUR_OPTIONAL
,
120 PROP_STD_LINE_COLOUR_OPTIONAL
,
121 PROP_STD_FILL_COLOUR_OPTIONAL
,
122 { "text", PROP_TYPE_TEXT
, 0, N_("Text"), NULL
, NULL
},
126 static PropDescription
*
127 actor_describe_props(Actor
*actor
)
129 if (actor_props
[0].quark
== 0) {
130 prop_desc_list_calculate_quarks(actor_props
);
135 static PropOffset actor_offsets
[] = {
136 ELEMENT_COMMON_PROPERTIES_OFFSETS
,
137 {"text",PROP_TYPE_TEXT
,offsetof(Actor
,text
)},
138 {"text_font",PROP_TYPE_FONT
,offsetof(Actor
,attrs
.font
)},
139 {"text_height",PROP_TYPE_REAL
,offsetof(Actor
,attrs
.height
)},
140 {"text_colour",PROP_TYPE_COLOUR
,offsetof(Actor
,attrs
.color
)},
141 {"line_colour",PROP_TYPE_COLOUR
,offsetof(Actor
,line_color
)},
142 {"fill_colour",PROP_TYPE_COLOUR
,offsetof(Actor
,fill_color
)},
147 actor_get_props(Actor
* actor
, GPtrArray
*props
)
149 text_get_attributes(actor
->text
,&actor
->attrs
);
150 object_get_props_from_offsets(&actor
->element
.object
,
151 actor_offsets
,props
);
155 actor_set_props(Actor
*actor
, GPtrArray
*props
)
157 object_set_props_from_offsets(&actor
->element
.object
,
158 actor_offsets
,props
);
159 apply_textattr_properties(props
,actor
->text
,"text",&actor
->attrs
);
160 actor_update_data(actor
);
164 actor_distance_from(Actor
*actor
, Point
*point
)
166 DiaObject
*obj
= &actor
->element
.object
;
167 return distance_rectangle_point(&obj
->bounding_box
, point
);
171 actor_select(Actor
*actor
, Point
*clicked_point
,
172 DiaRenderer
*interactive_renderer
)
174 text_set_cursor(actor
->text
, clicked_point
, interactive_renderer
);
175 text_grab_focus(actor
->text
, &actor
->element
.object
);
176 element_update_handles(&actor
->element
);
180 actor_move_handle(Actor
*actor
, Handle
*handle
,
181 Point
*to
, ConnectionPoint
*cp
,
182 HandleMoveReason reason
, ModifierKeys modifiers
)
187 assert(handle
!=NULL
);
190 assert(handle
->id
< 8);
192 oc
= element_move_handle (&(actor
->element
), handle
->id
, to
, cp
, reason
, modifiers
);
193 actor_update_data (actor
);
198 actor_move(Actor
*actor
, Point
*to
)
200 Element
*elem
= &actor
->element
;
203 elem
->corner
.x
-= elem
->width
/2.0;
204 elem
->corner
.y
-= elem
->height
/ 2.0;
206 actor_update_data(actor
);
212 actor_draw(Actor
*actor
, DiaRenderer
*renderer
)
214 DiaRendererClass
*renderer_ops
= DIA_RENDERER_GET_CLASS (renderer
);
218 Point ch
, cb
, p1
, p2
;
221 assert(actor
!= NULL
);
222 assert(renderer
!= NULL
);
224 elem
= &actor
->element
;
230 actor_height
= elem
->height
- actor
->text
->height
;
232 renderer_ops
->set_fillstyle(renderer
, FILLSTYLE_SOLID
);
233 renderer_ops
->set_linewidth(renderer
, ACTOR_LINEWIDTH
);
234 renderer_ops
->set_linestyle(renderer
, LINESTYLE_SOLID
);
236 r
= ACTOR_HEAD(actor_height
);
239 ch
.y
= y
+ r
+ ACTOR_MARGIN_Y
;
241 cb
.y
= ch
.y
+ r1
+ r
;
244 renderer_ops
->fill_ellipse(renderer
,
248 renderer_ops
->draw_ellipse(renderer
,
256 p1
.y
= p2
.y
= ch
.y
+ r
;
257 renderer_ops
->draw_line(renderer
,
264 renderer_ops
->draw_line(renderer
,
269 p2
.y
= y
+ ACTOR_BODY(actor_height
);
270 renderer_ops
->draw_line(renderer
,
275 renderer_ops
->draw_line(renderer
,
279 text_draw(actor
->text
, renderer
);
283 actor_update_data(Actor
*actor
)
285 Element
*elem
= &actor
->element
;
286 DiaObject
*obj
= &elem
->object
;
291 text_calc_boundingbox(actor
->text
, &text_box
);
294 if (elem
->width
< ACTOR_WIDTH
+ ACTOR_MARGIN_X
)
295 elem
->width
= ACTOR_WIDTH
+ ACTOR_MARGIN_X
;
296 if (elem
->height
< ACTOR_HEIGHT
+ actor
->text
->height
)
297 elem
->height
= ACTOR_HEIGHT
+ actor
->text
->height
;
298 actor_height
= elem
->height
- actor
->text
->height
;
300 /* Update connections: */
301 element_update_connections_rectangle(elem
, actor
->connections
);
303 element_update_boundingbox(elem
);
306 p
.x
+= elem
->width
/2;
307 p
.y
+= actor_height
+ actor
->text
->ascent
;
308 text_set_position(actor
->text
, &p
);
310 /* Add bounding box for text: */
311 rectangle_union(&obj
->bounding_box
, &text_box
);
313 obj
->position
= elem
->corner
;
314 obj
->position
.x
+= elem
->width
/2.0;
315 obj
->position
.y
+= elem
->height
/ 2.0;
317 element_update_handles(elem
);
321 actor_create(Point
*startpoint
,
333 actor
= g_malloc0(sizeof(Actor
));
334 elem
= &actor
->element
;
337 obj
->type
= &actor_type
;
338 obj
->ops
= &actor_ops
;
339 elem
->corner
= *startpoint
;
340 elem
->width
= ACTOR_WIDTH
;
341 elem
->height
= ACTOR_HEIGHT
;
343 actor
->line_color
= attributes_get_foreground();
344 actor
->fill_color
= attributes_get_background();
346 font
= dia_font_new_from_style (DIA_FONT_SANS
, 0.8);
348 p
.x
+= ACTOR_MARGIN_X
;
349 p
.y
+= ACTOR_HEIGHT
- dia_font_descent(_("Actor"),font
, 0.8);
351 actor
->text
= new_text(_("Actor"),
352 font
, 0.8, &p
, &color_black
, ALIGN_CENTER
);
353 dia_font_unref(font
);
355 text_get_attributes(actor
->text
,&actor
->attrs
);
357 element_init(elem
, 8, NUM_CONNECTIONS
);
359 for (i
=0;i
<NUM_CONNECTIONS
;i
++) {
360 obj
->connections
[i
] = &actor
->connections
[i
];
361 actor
->connections
[i
].object
= obj
;
362 actor
->connections
[i
].connected
= NULL
;
364 actor
->connections
[8].flags
= CP_FLAGS_MAIN
;
365 elem
->extra_spacing
.border_trans
= ACTOR_LINEWIDTH
/2.0;
366 actor_update_data(actor
);
369 obj
->handles
[i
]->type
= HANDLE_NON_MOVABLE
;
374 return &actor
->element
.object
;
378 actor_destroy(Actor
*actor
)
380 text_destroy(actor
->text
);
382 element_destroy(&actor
->element
);
386 actor_load(ObjectNode obj_node
, int version
, const char *filename
)
388 return object_load_using_properties(&actor_type
,
389 obj_node
,version
,filename
);