作図ソフト dia の改良版
リビジョン | 6dd3ff6dc6138118aaede44dec6c7d3b59aafb18 (tree) |
---|---|
日時 | 2004-05-06 17:01:45 |
作者 | Lars Clausen <lclausen@src....> |
コミッター | Lars Clausen |
Forgot to add these files.
@@ -0,0 +1,430 @@ | ||
1 | +/* Dia -- an diagram creation/manipulation program | |
2 | + * Copyright (C) 1998 Alexander Larsson | |
3 | + * | |
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. | |
8 | + * | |
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. | |
13 | + * | |
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. | |
17 | + */ | |
18 | + | |
19 | +/* Copyright 2003, W. Borgert <debacle@debian.org> | |
20 | + copied a lot from UML/actor.c */ | |
21 | + | |
22 | +#ifdef HAVE_CONFIG_H | |
23 | +#include <config.h> | |
24 | +#endif | |
25 | + | |
26 | +#include <assert.h> | |
27 | +#include <math.h> | |
28 | +#include <string.h> | |
29 | + | |
30 | +#include "intl.h" | |
31 | +#include "object.h" | |
32 | +#include "element.h" | |
33 | +#include "diarenderer.h" | |
34 | +#include "attributes.h" | |
35 | +#include "text.h" | |
36 | +#include "properties.h" | |
37 | + | |
38 | +#include "pixmaps/basestation.xpm" | |
39 | + | |
40 | +typedef struct _Basestation Basestation; | |
41 | +struct _Basestation { | |
42 | + Element element; | |
43 | + | |
44 | + ConnectionPoint connections[8]; | |
45 | + | |
46 | + Color line_colour; | |
47 | + Color fill_colour; | |
48 | + | |
49 | + Text *text; | |
50 | + TextAttributes attrs; | |
51 | + | |
52 | + int sectors; /* oftenly 3 or 4, always >= 1, but | |
53 | + check is missing */ | |
54 | +}; | |
55 | + | |
56 | +#define BASESTATION_WIDTH 0.8 | |
57 | +#define BASESTATION_HEIGHT 4.0 | |
58 | +#define BASESTATION_LINEWIDTH 0.1 | |
59 | + | |
60 | +static real basestation_distance_from(Basestation *basestation, | |
61 | + Point *point); | |
62 | +static void basestation_select(Basestation *basestation, | |
63 | + Point *clicked_point, | |
64 | + DiaRenderer *interactive_renderer); | |
65 | +static ObjectChange | |
66 | + *basestation_move_handle(Basestation *basestation, Handle *handle, | |
67 | + Point *to, ConnectionPoint *cp, | |
68 | + HandleMoveReason reason, | |
69 | + ModifierKeys modifiers); | |
70 | +static ObjectChange *basestation_move(Basestation *basestation, Point *to); | |
71 | +static void basestation_draw(Basestation *basestation, | |
72 | + DiaRenderer *renderer); | |
73 | +static Object *basestation_create(Point *startpoint, | |
74 | + void *user_data, | |
75 | + Handle **handle1, | |
76 | + Handle **handle2); | |
77 | +static void basestation_destroy(Basestation *basestation); | |
78 | +static Object *basestation_load(ObjectNode obj_node, | |
79 | + int version, | |
80 | + const char *filename); | |
81 | +static PropDescription | |
82 | + *basestation_describe_props(Basestation *basestation); | |
83 | +static void basestation_get_props(Basestation *basestation, | |
84 | + GPtrArray *props); | |
85 | +static void basestation_set_props(Basestation *basestation, | |
86 | + GPtrArray *props); | |
87 | +static void basestation_update_data(Basestation *basestation); | |
88 | + | |
89 | +static ObjectTypeOps basestation_type_ops = | |
90 | + { | |
91 | + (CreateFunc) basestation_create, | |
92 | + (LoadFunc) basestation_load, | |
93 | + (SaveFunc) object_save_using_properties, | |
94 | + (GetDefaultsFunc) NULL, | |
95 | + (ApplyDefaultsFunc) NULL | |
96 | + }; | |
97 | + | |
98 | +ObjectType basestation_type = | |
99 | + { | |
100 | + "Network - Base Station", /* name */ | |
101 | + 0, /* version */ | |
102 | + (char **) basestation_xpm, /* pixmap */ | |
103 | + | |
104 | + &basestation_type_ops /* ops */ | |
105 | + }; | |
106 | + | |
107 | +static ObjectOps basestation_ops = { | |
108 | + (DestroyFunc) basestation_destroy, | |
109 | + (DrawFunc) basestation_draw, | |
110 | + (DistanceFunc) basestation_distance_from, | |
111 | + (SelectFunc) basestation_select, | |
112 | + (CopyFunc) object_copy_using_properties, | |
113 | + (MoveFunc) basestation_move, | |
114 | + (MoveHandleFunc) basestation_move_handle, | |
115 | + (GetPropertiesFunc) object_create_props_dialog, | |
116 | + (ApplyPropertiesFunc) object_apply_props_from_dialog, | |
117 | + (ObjectMenuFunc) NULL, | |
118 | + (DescribePropsFunc) basestation_describe_props, | |
119 | + (GetPropsFunc) basestation_get_props, | |
120 | + (SetPropsFunc) basestation_set_props, | |
121 | +}; | |
122 | + | |
123 | +static PropDescription basestation_props[] = { | |
124 | + ELEMENT_COMMON_PROPERTIES, | |
125 | + PROP_STD_LINE_COLOUR, | |
126 | + PROP_STD_FILL_COLOUR, | |
127 | + PROP_STD_TEXT_FONT, | |
128 | + PROP_STD_TEXT_HEIGHT, | |
129 | + PROP_STD_TEXT_COLOUR, | |
130 | + PROP_STD_TEXT_ALIGNMENT, | |
131 | + { "text", PROP_TYPE_TEXT, 0, N_("Text"), NULL, NULL }, | |
132 | + { "sectors", PROP_TYPE_INT, PROP_FLAG_VISIBLE, | |
133 | + N_("Sectors"), NULL, NULL }, | |
134 | + PROP_DESC_END | |
135 | +}; | |
136 | + | |
137 | +static PropDescription * | |
138 | +basestation_describe_props(Basestation *basestation) | |
139 | +{ | |
140 | + if (basestation_props[0].quark == 0) { | |
141 | + prop_desc_list_calculate_quarks(basestation_props); | |
142 | + } | |
143 | + return basestation_props; | |
144 | +} | |
145 | + | |
146 | +static PropOffset basestation_offsets[] = { | |
147 | + ELEMENT_COMMON_PROPERTIES_OFFSETS, | |
148 | + {"line_colour", PROP_TYPE_COLOUR, offsetof(Basestation, line_colour)}, | |
149 | + {"fill_colour", PROP_TYPE_COLOUR, offsetof(Basestation, fill_colour)}, | |
150 | + {"text", PROP_TYPE_TEXT, offsetof(Basestation, text)}, | |
151 | + {"text_font", PROP_TYPE_FONT, offsetof(Basestation, attrs.font)}, | |
152 | + {"text_height", PROP_TYPE_REAL, offsetof(Basestation, attrs.height)}, | |
153 | + {"text_colour", PROP_TYPE_COLOUR, offsetof(Basestation, attrs.color)}, | |
154 | + {"text_alignment", PROP_TYPE_ENUM, | |
155 | + offsetof(Basestation, attrs.alignment)}, | |
156 | + {"sectors", PROP_TYPE_INT, offsetof(Basestation, sectors)}, | |
157 | + { NULL, 0, 0 }, | |
158 | +}; | |
159 | + | |
160 | +static void | |
161 | +basestation_get_props(Basestation * basestation, GPtrArray *props) | |
162 | +{ | |
163 | + text_get_attributes(basestation->text,&basestation->attrs); | |
164 | + object_get_props_from_offsets(&basestation->element.object, | |
165 | + basestation_offsets,props); | |
166 | +} | |
167 | + | |
168 | +static void | |
169 | +basestation_set_props(Basestation *basestation, GPtrArray *props) | |
170 | +{ | |
171 | + object_set_props_from_offsets(&basestation->element.object, | |
172 | + basestation_offsets, props); | |
173 | + apply_textattr_properties(props,basestation->text, | |
174 | + "text", &basestation->attrs); | |
175 | + basestation_update_data(basestation); | |
176 | +} | |
177 | + | |
178 | +static real | |
179 | +basestation_distance_from(Basestation *basestation, Point *point) | |
180 | +{ | |
181 | + Object *obj = &basestation->element.object; | |
182 | + return distance_rectangle_point(&obj->bounding_box, point); | |
183 | +} | |
184 | + | |
185 | +static void | |
186 | +basestation_select(Basestation *basestation, Point *clicked_point, | |
187 | + DiaRenderer *interactive_renderer) | |
188 | +{ | |
189 | + text_set_cursor(basestation->text, clicked_point, interactive_renderer); | |
190 | + text_grab_focus(basestation->text, &basestation->element.object); | |
191 | + element_update_handles(&basestation->element); | |
192 | +} | |
193 | + | |
194 | +static ObjectChange* | |
195 | +basestation_move_handle(Basestation *basestation, Handle *handle, | |
196 | + Point *to, ConnectionPoint *cp, | |
197 | + HandleMoveReason reason, ModifierKeys modifiers) | |
198 | +{ | |
199 | + assert(basestation!=NULL); | |
200 | + assert(handle!=NULL); | |
201 | + assert(to!=NULL); | |
202 | + | |
203 | + assert(handle->id < 8); | |
204 | + | |
205 | + return NULL; | |
206 | +} | |
207 | + | |
208 | +static ObjectChange* | |
209 | +basestation_move(Basestation *basestation, Point *to) | |
210 | +{ | |
211 | + Element *elem = &basestation->element; | |
212 | + | |
213 | + elem->corner = *to; | |
214 | + elem->corner.x -= elem->width/2.0; | |
215 | + elem->corner.y -= elem->height / 2.0; | |
216 | + | |
217 | + basestation_update_data(basestation); | |
218 | + | |
219 | + return NULL; | |
220 | +} | |
221 | + | |
222 | +static void | |
223 | +basestation_draw(Basestation *basestation, DiaRenderer *renderer) | |
224 | +{ | |
225 | + DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); | |
226 | + Element *elem; | |
227 | + real x, y, w, h; | |
228 | + real r = BASESTATION_WIDTH/2.0; | |
229 | + Point ct, cb, p1, p2; | |
230 | + Point points[6]; | |
231 | + | |
232 | + assert(basestation != NULL); | |
233 | + assert(renderer != NULL); | |
234 | + | |
235 | + elem = &basestation->element; | |
236 | + | |
237 | + x = elem->corner.x; | |
238 | + y = elem->corner.y + r; | |
239 | + w = elem->width; | |
240 | + h = elem->height - r; | |
241 | + | |
242 | + renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID); | |
243 | + renderer_ops->set_linejoin(renderer, LINEJOIN_ROUND); | |
244 | + renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID); | |
245 | + renderer_ops->set_linewidth(renderer, BASESTATION_LINEWIDTH); | |
246 | + | |
247 | + ct.x = x + w/2.0; | |
248 | + ct.y = y + r/2.0; | |
249 | + cb.x = ct.x; | |
250 | + cb.y = ct.y + h - r; | |
251 | + | |
252 | + /* antenna 1 */ | |
253 | + points[0] = ct; points[0].x -= r/4.0; points[0].y -= 3.0*r/4.0; | |
254 | + points[1] = ct; points[1].x += r/4.0; points[1].y -= 3.0*r/4.0; | |
255 | + points[2] = ct; points[2].x += r/4.0; points[2].y += 1.0; | |
256 | + points[3] = ct; points[3].x -= r/4.0; points[3].y += 1.0; | |
257 | + renderer_ops->fill_polygon(renderer, points, 4, | |
258 | + &basestation->fill_colour); | |
259 | + renderer_ops->draw_polygon(renderer, points, 4, | |
260 | + &basestation->line_colour); | |
261 | + /* bottom */ | |
262 | + renderer_ops->fill_ellipse(renderer, &cb, r, r/2.0, | |
263 | + &basestation->fill_colour); | |
264 | + renderer_ops->draw_arc(renderer, &cb, r, r/2.0, 180, 0, | |
265 | + &basestation->line_colour); | |
266 | + /* bar */ | |
267 | + p1 = ct; | |
268 | + p1.x -= r/2.0; | |
269 | + p2 = cb; | |
270 | + p2.x += r/2.0; | |
271 | + renderer_ops->fill_rect(renderer, &p1, &p2, | |
272 | + &basestation->fill_colour); | |
273 | + p2.x -= r; | |
274 | + renderer_ops->draw_line(renderer, &p1, &p2, | |
275 | + &basestation->line_colour); | |
276 | + p1.x += r; | |
277 | + p2.x += r; | |
278 | + renderer_ops->draw_line(renderer, &p1, &p2, | |
279 | + &basestation->line_colour); | |
280 | + /* top */ | |
281 | + renderer_ops->fill_ellipse(renderer, &ct, r, r/2.0, | |
282 | + &basestation->fill_colour); | |
283 | + renderer_ops->draw_ellipse(renderer, &ct, r, r/2.0, | |
284 | + &basestation->line_colour); | |
285 | + /* antenna 2 */ | |
286 | + points[0] = ct; points[0].x += r/4.0; points[0].y -= 0; | |
287 | + points[1] = ct; points[1].x += 3.0*r/4.0; points[1].y -= r/2.0; | |
288 | + points[2] = ct; points[2].x += 3.0*r/4.0; points[2].y += 1.0 - r/2.0; | |
289 | + points[3] = ct; points[3].x += r/4.0; points[3].y += 1.0; | |
290 | + renderer_ops->fill_polygon(renderer, points, 4, | |
291 | + &basestation->fill_colour); | |
292 | + renderer_ops->draw_polygon(renderer, points, 4, | |
293 | + &basestation->line_colour); | |
294 | + /* antenna 3 */ | |
295 | + points[0] = ct; points[0].x -= r/4.0; points[0].y -= 0; | |
296 | + points[1] = ct; points[1].x -= 3.0*r/4.0; points[1].y -= r/2.0; | |
297 | + points[2] = ct; points[2].x -= 3.0*r/4.0; points[2].y += 1.0 - r/2.0; | |
298 | + points[3] = ct; points[3].x -= r/4.0; points[3].y += 1.0; | |
299 | + renderer_ops->fill_polygon(renderer, points, 4, | |
300 | + &basestation->fill_colour); | |
301 | + renderer_ops->draw_polygon(renderer, points, 4, | |
302 | + &basestation->line_colour); | |
303 | + text_draw(basestation->text, renderer); | |
304 | +} | |
305 | + | |
306 | +static void | |
307 | +basestation_update_data(Basestation *basestation) | |
308 | +{ | |
309 | + Element *elem = &basestation->element; | |
310 | + Object *obj = &elem->object; | |
311 | + Rectangle text_box; | |
312 | + Point p; | |
313 | + | |
314 | + text_calc_boundingbox(basestation->text, &text_box); | |
315 | + | |
316 | + elem->width = BASESTATION_WIDTH; | |
317 | + elem->height = BASESTATION_HEIGHT+basestation->text->height; | |
318 | + | |
319 | + /* Update connections: */ | |
320 | + basestation->connections[0].pos.x = elem->corner.x; | |
321 | + basestation->connections[0].pos.y = elem->corner.y; | |
322 | + basestation->connections[0].directions = DIR_NORTH|DIR_WEST; | |
323 | + basestation->connections[1].pos.x = elem->corner.x + elem->width / 2.0; | |
324 | + basestation->connections[1].pos.y = elem->corner.y; | |
325 | + basestation->connections[1].directions = DIR_NORTH; | |
326 | + basestation->connections[2].pos.x = elem->corner.x + elem->width; | |
327 | + basestation->connections[2].pos.y = elem->corner.y; | |
328 | + basestation->connections[2].directions = DIR_NORTH|DIR_EAST; | |
329 | + basestation->connections[3].pos.x = elem->corner.x; | |
330 | + basestation->connections[3].pos.y = elem->corner.y + elem->height / 2.0; | |
331 | + basestation->connections[3].directions = DIR_WEST; | |
332 | + basestation->connections[4].pos.x = elem->corner.x + elem->width; | |
333 | + basestation->connections[4].pos.y = elem->corner.y + elem->height / 2.0; | |
334 | + basestation->connections[4].directions = DIR_EAST; | |
335 | + basestation->connections[5].pos.x = elem->corner.x; | |
336 | + basestation->connections[5].pos.y = elem->corner.y + elem->height; | |
337 | + basestation->connections[5].directions = DIR_SOUTH|DIR_WEST; | |
338 | + basestation->connections[6].pos.x = elem->corner.x + elem->width / 2.0; | |
339 | + basestation->connections[6].pos.y = elem->corner.y + elem->height; | |
340 | + basestation->connections[6].directions = DIR_SOUTH; | |
341 | + basestation->connections[7].pos.x = elem->corner.x + elem->width; | |
342 | + basestation->connections[7].pos.y = elem->corner.y + elem->height; | |
343 | + basestation->connections[7].directions = DIR_SOUTH|DIR_EAST; | |
344 | + | |
345 | + element_update_boundingbox(elem); | |
346 | + | |
347 | + p = elem->corner; | |
348 | + p.x += elem->width/2; | |
349 | + p.y += elem->height + basestation->text->ascent; | |
350 | + text_set_position(basestation->text, &p); | |
351 | + | |
352 | + /* Add bounding box for text: */ | |
353 | + rectangle_union(&obj->bounding_box, &text_box); | |
354 | + | |
355 | + obj->position = elem->corner; | |
356 | + obj->position.x += elem->width/2.0; | |
357 | + obj->position.y += elem->height/2.0; | |
358 | + | |
359 | + element_update_handles(elem); | |
360 | +} | |
361 | + | |
362 | +static Object * | |
363 | +basestation_create(Point *startpoint, | |
364 | + void *user_data, | |
365 | + Handle **handle1, | |
366 | + Handle **handle2) | |
367 | +{ | |
368 | + Basestation *basestation; | |
369 | + Element *elem; | |
370 | + Object *obj; | |
371 | + Point p; | |
372 | + DiaFont *font; | |
373 | + int i; | |
374 | + | |
375 | + basestation = g_new0(Basestation, 1); | |
376 | + elem = &basestation->element; | |
377 | + obj = &elem->object; | |
378 | + | |
379 | + obj->type = &basestation_type; | |
380 | + obj->ops = &basestation_ops; | |
381 | + elem->corner = *startpoint; | |
382 | + elem->width = BASESTATION_WIDTH; | |
383 | + elem->height = BASESTATION_HEIGHT; | |
384 | + | |
385 | + font = dia_font_new_from_style (DIA_FONT_MONOSPACE, 0.8); | |
386 | + p = *startpoint; | |
387 | + p.y += BASESTATION_HEIGHT - | |
388 | + dia_font_descent(_("Base Station"), font, 0.8); | |
389 | + | |
390 | + basestation->text = new_text(_("Base Station"), | |
391 | + font, 0.8, &p, &color_black, ALIGN_CENTER); | |
392 | + dia_font_unref(font); | |
393 | + text_get_attributes(basestation->text,&basestation->attrs); | |
394 | + basestation->line_colour = color_black; | |
395 | + basestation->fill_colour = color_white; | |
396 | + basestation->sectors = 3; | |
397 | + | |
398 | + element_init(elem, 8, 8); | |
399 | + | |
400 | + for (i=0; i<8; i++) { | |
401 | + obj->connections[i] = &basestation->connections[i]; | |
402 | + basestation->connections[i].object = obj; | |
403 | + basestation->connections[i].connected = NULL; | |
404 | + } | |
405 | + elem->extra_spacing.border_trans = BASESTATION_LINEWIDTH/2.0; | |
406 | + basestation_update_data(basestation); | |
407 | + | |
408 | + for (i=0; i<8; i++) { | |
409 | + obj->handles[i]->type = HANDLE_NON_MOVABLE; | |
410 | + } | |
411 | + | |
412 | + *handle1 = NULL; | |
413 | + *handle2 = NULL; | |
414 | + return &basestation->element.object; | |
415 | +} | |
416 | + | |
417 | +static void | |
418 | +basestation_destroy(Basestation *basestation) | |
419 | +{ | |
420 | + text_destroy(basestation->text); | |
421 | + | |
422 | + element_destroy(&basestation->element); | |
423 | +} | |
424 | + | |
425 | +static Object * | |
426 | +basestation_load(ObjectNode obj_node, int version, const char *filename) | |
427 | +{ | |
428 | + return object_load_using_properties(&basestation_type, | |
429 | + obj_node, version, filename); | |
430 | +} |
@@ -0,0 +1,28 @@ | ||
1 | +/* XPM */ | |
2 | +static char * basestation_xpm[] = { | |
3 | +"22 22 3 1", | |
4 | +" c None", | |
5 | +". c #000000", | |
6 | +"+ c #FFFFFF", | |
7 | +" . . ", | |
8 | +" .. . .. ", | |
9 | +" .+.+.+. ", | |
10 | +" .+.+.+. ", | |
11 | +" .+.+.+. ", | |
12 | +" .+.+.+. ", | |
13 | +" ..+.. ", | |
14 | +" .+. ", | |
15 | +" .+. ", | |
16 | +" .+. ", | |
17 | +" .+. ", | |
18 | +" .+. ", | |
19 | +" .+. ", | |
20 | +" .+. ", | |
21 | +" .+. ", | |
22 | +" .+. ", | |
23 | +" .+. ", | |
24 | +" .+. ", | |
25 | +" .+. ", | |
26 | +" .+. ", | |
27 | +" .+. ", | |
28 | +" . "}; |
@@ -0,0 +1,28 @@ | ||
1 | +/* XPM */ | |
2 | +static char * radiocell_xpm[] = { | |
3 | +"22 22 3 1", | |
4 | +" c None", | |
5 | +". c #000000", | |
6 | +"+ c #FFFFFF", | |
7 | +" ", | |
8 | +" .......... ", | |
9 | +" .++++++++++. ", | |
10 | +" .++++++++++. ", | |
11 | +" .++++++++++++. ", | |
12 | +" .++++++++++++++. ", | |
13 | +" .++++++++++++++. ", | |
14 | +" .++++++++++++++++. ", | |
15 | +" .++++++++++++++++++. ", | |
16 | +" .++++++++++++++++++. ", | |
17 | +".++++++++++++++++++++.", | |
18 | +".++++++++++++++++++++.", | |
19 | +" .++++++++++++++++++. ", | |
20 | +" .++++++++++++++++++. ", | |
21 | +" .++++++++++++++++. ", | |
22 | +" .++++++++++++++. ", | |
23 | +" .++++++++++++++. ", | |
24 | +" .++++++++++++. ", | |
25 | +" .++++++++++. ", | |
26 | +" .++++++++++. ", | |
27 | +" .......... ", | |
28 | +" "}; |
@@ -0,0 +1,380 @@ | ||
1 | +/* Dia -- an diagram creation/manipulation program | |
2 | + * Copyright (C) 1998 Alexander Larsson | |
3 | + * | |
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. | |
8 | + * | |
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. | |
13 | + * | |
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. | |
17 | + */ | |
18 | + | |
19 | +/* Copyright 2003, W. Borgert <debacle@debian.org> | |
20 | + copied a lot from UML/large_package.c and standard/polygon.c */ | |
21 | + | |
22 | +#ifdef HAVE_CONFIG_H | |
23 | +#include <config.h> | |
24 | +#endif | |
25 | + | |
26 | +#include <assert.h> | |
27 | +#include <math.h> | |
28 | +#include <string.h> | |
29 | + | |
30 | +#include "intl.h" | |
31 | +#include "object.h" | |
32 | +#include "polyshape.h" | |
33 | +#include "diarenderer.h" | |
34 | +#include "attributes.h" | |
35 | +#include "text.h" | |
36 | +#include "properties.h" | |
37 | + | |
38 | +#include "network.h" | |
39 | + | |
40 | +#include "pixmaps/radiocell.xpm" | |
41 | + | |
42 | +/* TODO? no visual effect ATM, but useful anyway */ | |
43 | +typedef enum { | |
44 | + MACRO_CELL, | |
45 | + MICRO_CELL, | |
46 | + PICO_CELL, | |
47 | +} CellType; | |
48 | + | |
49 | +/* TODO: add different cell technologies, like GSM, UMTS, ... */ | |
50 | + | |
51 | +typedef struct _RadioCell RadioCell; | |
52 | + | |
53 | +struct _RadioCell { | |
54 | + PolyShape poly; /* always 1st! */ | |
55 | + CellType celltype; | |
56 | + real radius; /* pseudo-radius */ | |
57 | + ConnectionPoint cp; /* connection point in the center */ | |
58 | + Color line_colour; | |
59 | + LineStyle line_style; | |
60 | + real dashlength; | |
61 | + real line_width; | |
62 | + gboolean show_background; | |
63 | + Color fill_colour; | |
64 | + Text *text; | |
65 | + TextAttributes attrs; | |
66 | + int subscribers; /* number of subscribers in this cell, | |
67 | + always >= 0, but check is missing */ | |
68 | +}; | |
69 | + | |
70 | +#define RADIOCELL_LINEWIDTH 0.1 | |
71 | +#define RADIOCELL_FONTHEIGHT 0.8 | |
72 | + | |
73 | +static real radiocell_distance_from(RadioCell *radiocell, Point *point); | |
74 | +static void radiocell_select(RadioCell *radiocell, Point *clicked_point, | |
75 | + DiaRenderer *interactive_renderer); | |
76 | +static ObjectChange* radiocell_move_handle(RadioCell *radiocell, | |
77 | + Handle *handle, | |
78 | + Point *to, ConnectionPoint *cp, | |
79 | + HandleMoveReason reason, | |
80 | + ModifierKeys modifiers); | |
81 | +static ObjectChange* radiocell_move(RadioCell *radiocell, Point *to); | |
82 | +static void radiocell_draw(RadioCell *radiocell, DiaRenderer *renderer); | |
83 | +static Object *radiocell_create(Point *startpoint, | |
84 | + void *user_data, | |
85 | + Handle **handle1, | |
86 | + Handle **handle2); | |
87 | +static void radiocell_destroy(RadioCell *radiocell); | |
88 | +static void radiocell_update_data(RadioCell *radiocell); | |
89 | +static PropDescription *radiocell_describe_props(RadioCell *radiocell); | |
90 | +static void radiocell_get_props(RadioCell *radiocell, GPtrArray *props); | |
91 | +static void radiocell_set_props(RadioCell *radiocell, GPtrArray *props); | |
92 | +static Object *radiocell_load(ObjectNode obj_node, int version, | |
93 | + const char *filename); | |
94 | + | |
95 | +static ObjectTypeOps radiocell_type_ops = | |
96 | +{ | |
97 | + (CreateFunc) radiocell_create, | |
98 | + (LoadFunc) radiocell_load, | |
99 | + (SaveFunc) object_save_using_properties, | |
100 | + (GetDefaultsFunc) NULL, | |
101 | + (ApplyDefaultsFunc) NULL | |
102 | +}; | |
103 | + | |
104 | +ObjectType radiocell_type = | |
105 | +{ | |
106 | + "Network - Radio Cell", /* name */ | |
107 | + 0, /* version */ | |
108 | + (char **) radiocell_xpm, /* pixmap */ | |
109 | + | |
110 | + &radiocell_type_ops /* ops */ | |
111 | +}; | |
112 | + | |
113 | +static ObjectOps radiocell_ops = { | |
114 | + (DestroyFunc) radiocell_destroy, | |
115 | + (DrawFunc) radiocell_draw, | |
116 | + (DistanceFunc) radiocell_distance_from, | |
117 | + (SelectFunc) radiocell_select, | |
118 | + (CopyFunc) object_copy_using_properties, | |
119 | + (MoveFunc) radiocell_move, | |
120 | + (MoveHandleFunc) radiocell_move_handle, | |
121 | + (GetPropertiesFunc) object_create_props_dialog, | |
122 | + (ApplyPropertiesFunc) object_apply_props_from_dialog, | |
123 | + (ObjectMenuFunc) NULL, | |
124 | + (DescribePropsFunc) radiocell_describe_props, | |
125 | + (GetPropsFunc) radiocell_get_props, | |
126 | + (SetPropsFunc) radiocell_set_props | |
127 | +}; | |
128 | + | |
129 | +static PropEnumData prop_cell_type_data[] = { | |
130 | + { N_("Macro Cell"), MACRO_CELL }, | |
131 | + { N_("Micro Cell"), MICRO_CELL }, | |
132 | + { N_("Pico Cell"), PICO_CELL }, | |
133 | + { NULL, 0} | |
134 | +}; | |
135 | + | |
136 | +static PropDescription radiocell_props[] = { | |
137 | + POLYSHAPE_COMMON_PROPERTIES, | |
138 | + { "radius", PROP_TYPE_REAL, 0, N_("Radius"), NULL, NULL }, | |
139 | + { "celltype", PROP_TYPE_ENUM, PROP_FLAG_VISIBLE, | |
140 | + N_("Cell Type:"), NULL, prop_cell_type_data }, | |
141 | + PROP_STD_LINE_WIDTH, | |
142 | + PROP_STD_LINE_COLOUR, | |
143 | + PROP_STD_LINE_STYLE, | |
144 | + PROP_STD_FILL_COLOUR, | |
145 | + PROP_STD_SHOW_BACKGROUND, | |
146 | + { "text", PROP_TYPE_TEXT, 0, N_("Text"), NULL, NULL }, | |
147 | + PROP_STD_TEXT_FONT, | |
148 | + PROP_STD_TEXT_HEIGHT, | |
149 | + PROP_STD_TEXT_COLOUR, | |
150 | + PROP_STD_TEXT_ALIGNMENT, | |
151 | + { "subscribers", PROP_TYPE_INT, PROP_FLAG_VISIBLE, | |
152 | + N_("Subscribers"), NULL, NULL }, | |
153 | + PROP_DESC_END | |
154 | +}; | |
155 | + | |
156 | +static PropDescription * | |
157 | +radiocell_describe_props(RadioCell *radiocell) | |
158 | +{ | |
159 | + if (radiocell_props[0].quark == 0) { | |
160 | + prop_desc_list_calculate_quarks(radiocell_props); | |
161 | + } | |
162 | + return radiocell_props; | |
163 | +} | |
164 | + | |
165 | +static PropOffset radiocell_offsets[] = { | |
166 | + POLYSHAPE_COMMON_PROPERTIES_OFFSETS, | |
167 | + { "radius", PROP_TYPE_REAL, offsetof(RadioCell, radius) }, | |
168 | + { "celltype", PROP_TYPE_ENUM, offsetof(RadioCell, celltype) }, | |
169 | + { "line_width", PROP_TYPE_REAL, offsetof(RadioCell, line_width) }, | |
170 | + { "line_colour", PROP_TYPE_COLOUR, offsetof(RadioCell, line_colour) }, | |
171 | + { "line_style", PROP_TYPE_LINESTYLE, | |
172 | + offsetof(RadioCell, line_style), offsetof(RadioCell, dashlength) }, | |
173 | + { "fill_colour", PROP_TYPE_COLOUR, offsetof(RadioCell, fill_colour) }, | |
174 | + { "show_background", PROP_TYPE_BOOL, | |
175 | + offsetof(RadioCell, show_background) }, | |
176 | + { "text", PROP_TYPE_TEXT, offsetof(RadioCell, text) }, | |
177 | + { "text_font", PROP_TYPE_FONT, offsetof(RadioCell, attrs.font) }, | |
178 | + { "text_height", PROP_TYPE_REAL, offsetof(RadioCell, attrs.height) }, | |
179 | + { "text_colour", PROP_TYPE_COLOUR, offsetof(RadioCell, attrs.color) }, | |
180 | + { "text_alignment", PROP_TYPE_ENUM, | |
181 | + offsetof(RadioCell, attrs.alignment) }, | |
182 | + { "subscribers", PROP_TYPE_INT, offsetof(RadioCell, subscribers) }, | |
183 | + { NULL, 0, 0 }, | |
184 | +}; | |
185 | + | |
186 | +static void | |
187 | +radiocell_get_props(RadioCell *radiocell, GPtrArray *props) | |
188 | +{ | |
189 | + text_get_attributes(radiocell->text, &radiocell->attrs); | |
190 | + object_get_props_from_offsets(&radiocell->poly.object, | |
191 | + radiocell_offsets, props); | |
192 | +} | |
193 | + | |
194 | +static void | |
195 | +radiocell_set_props(RadioCell *radiocell, GPtrArray *props) | |
196 | +{ | |
197 | + object_set_props_from_offsets(&radiocell->poly.object, | |
198 | + radiocell_offsets, props); | |
199 | + apply_textattr_properties(props, radiocell->text, | |
200 | + "text", &radiocell->attrs); | |
201 | + radiocell_update_data(radiocell); | |
202 | +} | |
203 | + | |
204 | +static real | |
205 | +radiocell_distance_from(RadioCell *radiocell, Point *point) | |
206 | +{ | |
207 | + return polyshape_distance_from(&radiocell->poly, point, | |
208 | + radiocell->line_width); | |
209 | +} | |
210 | + | |
211 | +static void | |
212 | +radiocell_select(RadioCell *radiocell, Point *clicked_point, | |
213 | + DiaRenderer *interactive_renderer) | |
214 | +{ | |
215 | + text_set_cursor(radiocell->text, clicked_point, interactive_renderer); | |
216 | + text_grab_focus(radiocell->text, &radiocell->poly.object); | |
217 | + polyshape_update_data(&radiocell->poly); | |
218 | +} | |
219 | + | |
220 | +static ObjectChange* | |
221 | +radiocell_move_handle(RadioCell *radiocell, Handle *handle, | |
222 | + Point *to, ConnectionPoint *cp, | |
223 | + HandleMoveReason reason, ModifierKeys modifiers) | |
224 | +{ | |
225 | + real distance = distance_point_point(&handle->pos, to); | |
226 | + gboolean larger = distance_point_point(&handle->pos, &radiocell->cp.pos) < | |
227 | + distance_point_point(to, &radiocell->cp.pos); | |
228 | + | |
229 | + /* TODO: this flickers terribly */ | |
230 | + radiocell->radius += distance * (larger? 1: -1); | |
231 | + if (radiocell->radius < 1.) | |
232 | + radiocell->radius = 1.; | |
233 | + radiocell_update_data(radiocell); | |
234 | + | |
235 | + return NULL; | |
236 | +} | |
237 | + | |
238 | +static ObjectChange* | |
239 | +radiocell_move(RadioCell *radiocell, Point *to) | |
240 | +{ | |
241 | + polyshape_move(&radiocell->poly, to); | |
242 | + radiocell->cp.pos = *to; | |
243 | + radiocell->cp.pos.x -= radiocell->radius; | |
244 | + radiocell_update_data(radiocell); | |
245 | + | |
246 | + return NULL; | |
247 | +} | |
248 | + | |
249 | +static void | |
250 | +radiocell_draw(RadioCell *radiocell, DiaRenderer *renderer) | |
251 | +{ | |
252 | + DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); | |
253 | + PolyShape *poly; | |
254 | + Point *points; | |
255 | + int n; | |
256 | + | |
257 | + assert(radiocell != NULL); | |
258 | + assert(renderer != NULL); | |
259 | + | |
260 | + poly = &radiocell->poly; | |
261 | + points = &poly->points[0]; | |
262 | + n = poly->numpoints; | |
263 | + | |
264 | + if (radiocell->show_background) { | |
265 | + renderer_ops->set_fillstyle(renderer, FILLSTYLE_SOLID); | |
266 | + renderer_ops->fill_polygon(renderer, points, n, &radiocell->fill_colour); | |
267 | + } | |
268 | + renderer_ops->set_linecaps(renderer, LINECAPS_BUTT); | |
269 | + renderer_ops->set_linejoin(renderer, LINEJOIN_MITER); | |
270 | + renderer_ops->set_linestyle(renderer, radiocell->line_style); | |
271 | + renderer_ops->set_linewidth(renderer, radiocell->line_width); | |
272 | + renderer_ops->set_dashlength(renderer, radiocell->dashlength); | |
273 | + renderer_ops->draw_polygon(renderer, points, n, &radiocell->line_colour); | |
274 | + | |
275 | + text_draw(radiocell->text, renderer); | |
276 | +} | |
277 | + | |
278 | +static void | |
279 | +radiocell_update_data(RadioCell *radiocell) | |
280 | +{ | |
281 | + PolyShape *poly = &radiocell->poly; | |
282 | + Object *obj = &poly->object; | |
283 | + ElementBBExtras *extra = &poly->extra_spacing; | |
284 | + Rectangle text_box; | |
285 | + Point textpos; | |
286 | + int i; | |
287 | + /* not exactly a regular hexagon, but this fits better in the grid */ | |
288 | + Point points[] = { { 1., 0. }, { .5, .75 }, { -.5, .75 }, | |
289 | + { -1., 0. }, { -.5, -.75 }, { .5, -.75 } }; | |
290 | + | |
291 | + /* TODO: the CP is invisible and does not yet work */ | |
292 | + radiocell->cp.pos.x = (poly->points[0].x + poly->points[3].x) / 2.; | |
293 | + radiocell->cp.pos.y = poly->points[0].y; | |
294 | + | |
295 | + for (i = 0; i < 6; i++) { | |
296 | + poly->points[i] = radiocell->cp.pos; | |
297 | + poly->points[i].x += radiocell->radius * points[i].x; | |
298 | + poly->points[i].y += radiocell->radius * points[i].y; | |
299 | + } | |
300 | + | |
301 | + /* Add bounding box for text: */ | |
302 | + text_calc_boundingbox(radiocell->text, NULL); | |
303 | + textpos.x = (poly->points[0].x + poly->points[3].x) / 2.; | |
304 | + textpos.y = poly->points[0].y - | |
305 | + (radiocell->text->height * (radiocell->text->numlines - 1) + | |
306 | + radiocell->text->descent) / 2.; | |
307 | + text_set_position(radiocell->text, &textpos); | |
308 | + text_calc_boundingbox(radiocell->text, &text_box); | |
309 | + polyshape_update_data(poly); | |
310 | + extra->border_trans = radiocell->line_width / 2.0; | |
311 | + polyshape_update_boundingbox(poly); | |
312 | + rectangle_union(&obj->bounding_box, &text_box); | |
313 | + obj->position = poly->points[0]; | |
314 | +} | |
315 | + | |
316 | +static Object * | |
317 | +radiocell_create(Point *startpoint, | |
318 | + void *user_data, | |
319 | + Handle **handle1, | |
320 | + Handle **handle2) | |
321 | +{ | |
322 | + RadioCell *radiocell; | |
323 | + PolyShape *poly; | |
324 | + Object *obj; | |
325 | + DiaFont *font; | |
326 | + | |
327 | + radiocell = g_new0(RadioCell, 1); | |
328 | + poly = &radiocell->poly; | |
329 | + obj = &poly->object; | |
330 | + obj->type = &radiocell_type; | |
331 | + obj->ops = &radiocell_ops; | |
332 | + obj->can_parent = TRUE; | |
333 | + | |
334 | + radiocell->celltype = MACRO_CELL; | |
335 | + radiocell->radius = 4.; | |
336 | + radiocell->subscribers = 1000; | |
337 | + | |
338 | + /* do not use default_properties.show_background here */ | |
339 | + radiocell->show_background = FALSE; | |
340 | + radiocell->fill_colour = color_white; | |
341 | + radiocell->line_colour = color_black; | |
342 | + radiocell->line_width = RADIOCELL_LINEWIDTH; | |
343 | + attributes_get_default_line_style(&radiocell->line_style, | |
344 | + &radiocell->dashlength); | |
345 | + | |
346 | + font = dia_font_new_from_style(DIA_FONT_MONOSPACE, RADIOCELL_FONTHEIGHT); | |
347 | + radiocell->text = new_text("", font, RADIOCELL_FONTHEIGHT, startpoint, | |
348 | + &color_black, ALIGN_CENTER); | |
349 | + dia_font_unref(font); | |
350 | + text_get_attributes(radiocell->text, &radiocell->attrs); | |
351 | + | |
352 | + polyshape_init(poly, 6); | |
353 | + | |
354 | + object_add_connectionpoint(&poly->object, &radiocell->cp); | |
355 | + obj->connections[0] = &radiocell->cp; | |
356 | + radiocell->cp.object = obj; | |
357 | + radiocell->cp.connected = NULL; | |
358 | + radiocell->cp.directions = DIR_ALL; | |
359 | + radiocell->cp.pos = *startpoint; | |
360 | + radiocell->cp.pos.x -= radiocell->radius; | |
361 | + | |
362 | + radiocell_update_data(radiocell); | |
363 | + *handle1 = poly->object.handles[0]; | |
364 | + *handle2 = poly->object.handles[2]; | |
365 | + return &radiocell->poly.object; | |
366 | +} | |
367 | + | |
368 | +static void | |
369 | +radiocell_destroy(RadioCell *radiocell) | |
370 | +{ | |
371 | + text_destroy(radiocell->text); | |
372 | + polyshape_destroy(&radiocell->poly); | |
373 | +} | |
374 | + | |
375 | +static Object * | |
376 | +radiocell_load(ObjectNode obj_node, int version, const char *filename) | |
377 | +{ | |
378 | + return object_load_using_properties(&radiocell_type, | |
379 | + obj_node, version, filename); | |
380 | +} |