2001-09-14 Hans Breuer <hans@breuer.org>
[dia.git] / objects / standard / zigzagline.c
blobdba9a3bee01db437f5400ea206623bfdc2aeb33c
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.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <assert.h>
24 #include <gtk/gtk.h>
25 #include <math.h>
27 #include "intl.h"
28 #include "object.h"
29 #include "orth_conn.h"
30 #include "connectionpoint.h"
31 #include "render.h"
32 #include "attributes.h"
33 #include "widgets.h"
34 #include "message.h"
35 #include "properties.h"
37 #include "pixmaps/zigzag.xpm"
39 #define DEFAULT_WIDTH 0.15
41 #define HANDLE_MIDDLE HANDLE_CUSTOM1
43 typedef struct _Zigzagline {
44 OrthConn orth;
46 Color line_color;
47 LineStyle line_style;
48 real dashlength;
49 real line_width;
50 Arrow start_arrow, end_arrow;
51 } Zigzagline;
54 static void zigzagline_move_handle(Zigzagline *zigzagline, Handle *handle,
55 Point *to, HandleMoveReason reason, ModifierKeys modifiers);
56 static void zigzagline_move(Zigzagline *zigzagline, Point *to);
57 static void zigzagline_select(Zigzagline *zigzagline, Point *clicked_point,
58 Renderer *interactive_renderer);
59 static void zigzagline_draw(Zigzagline *zigzagline, Renderer *renderer);
60 static Object *zigzagline_create(Point *startpoint,
61 void *user_data,
62 Handle **handle1,
63 Handle **handle2);
64 static real zigzagline_distance_from(Zigzagline *zigzagline, Point *point);
65 static void zigzagline_update_data(Zigzagline *zigzagline);
66 static void zigzagline_destroy(Zigzagline *zigzagline);
67 static Object *zigzagline_copy(Zigzagline *zigzagline);
68 static DiaMenu *zigzagline_get_object_menu(Zigzagline *zigzagline,
69 Point *clickedpoint);
71 static PropDescription *zigzagline_describe_props(Zigzagline *zigzagline);
72 static void zigzagline_get_props(Zigzagline *zigzagline, GPtrArray *props);
73 static void zigzagline_set_props(Zigzagline *zigzagline, GPtrArray *props);
75 static void zigzagline_save(Zigzagline *zigzagline, ObjectNode obj_node,
76 const char *filename);
77 static Object *zigzagline_load(ObjectNode obj_node, int version,
78 const char *filename);
79 /* static GtkWidget *zigzagline_get_defaults();
80 static void zigzagline_apply_defaults(); */
82 static ObjectTypeOps zigzagline_type_ops =
84 (CreateFunc)zigzagline_create, /* create */
85 (LoadFunc) zigzagline_load, /* load */
86 (SaveFunc) zigzagline_save, /* save */
87 (GetDefaultsFunc) NULL,/*zigzagline_get_defaults*/
88 (ApplyDefaultsFunc) NULL /*zigzagline_apply_defaults*/
91 static ObjectType zigzagline_type =
93 "Standard - ZigZagLine", /* name */
94 0, /* version */
95 (char **) zigzag_xpm, /* pixmap */
97 &zigzagline_type_ops /* ops */
100 ObjectType *_zigzagline_type = (ObjectType *) &zigzagline_type;
103 static ObjectOps zigzagline_ops = {
104 (DestroyFunc) zigzagline_destroy,
105 (DrawFunc) zigzagline_draw,
106 (DistanceFunc) zigzagline_distance_from,
107 (SelectFunc) zigzagline_select,
108 (CopyFunc) zigzagline_copy,
109 (MoveFunc) zigzagline_move,
110 (MoveHandleFunc) zigzagline_move_handle,
111 (GetPropertiesFunc) object_create_props_dialog,
112 (ApplyPropertiesFunc) object_apply_props_from_dialog,
113 (ObjectMenuFunc) zigzagline_get_object_menu,
114 (DescribePropsFunc) zigzagline_describe_props,
115 (GetPropsFunc) zigzagline_get_props,
116 (SetPropsFunc) zigzagline_set_props,
119 static PropDescription zigzagline_props[] = {
120 OBJECT_COMMON_PROPERTIES,
121 PROP_STD_LINE_WIDTH,
122 PROP_STD_LINE_COLOUR,
123 PROP_STD_LINE_STYLE,
124 PROP_STD_START_ARROW,
125 PROP_STD_END_ARROW,
126 PROP_DESC_END
129 static PropDescription *
130 zigzagline_describe_props(Zigzagline *zigzagline)
132 if (zigzagline_props[0].quark == 0)
133 prop_desc_list_calculate_quarks(zigzagline_props);
134 return zigzagline_props;
137 static PropOffset zigzagline_offsets[] = {
138 OBJECT_COMMON_PROPERTIES_OFFSETS,
139 { "line_width", PROP_TYPE_REAL, offsetof(Zigzagline, line_width) },
140 { "line_colour", PROP_TYPE_COLOUR, offsetof(Zigzagline, line_color) },
141 { "line_style", PROP_TYPE_LINESTYLE,
142 offsetof(Zigzagline, line_style), offsetof(Zigzagline, dashlength) },
143 { "start_arrow", PROP_TYPE_ARROW, offsetof(Zigzagline, start_arrow) },
144 { "end_arrow", PROP_TYPE_ARROW, offsetof(Zigzagline, end_arrow) },
145 { NULL, 0, 0 }
148 static void
149 zigzagline_get_props(Zigzagline *zigzagline, GPtrArray *props)
151 object_get_props_from_offsets(&zigzagline->orth.object, zigzagline_offsets,
152 props);
155 static void
156 zigzagline_set_props(Zigzagline *zigzagline, GPtrArray *props)
158 object_set_props_from_offsets(&zigzagline->orth.object, zigzagline_offsets,
159 props);
160 zigzagline_update_data(zigzagline);
163 static real
164 zigzagline_distance_from(Zigzagline *zigzagline, Point *point)
166 OrthConn *orth = &zigzagline->orth;
167 return orthconn_distance_from(orth, point, zigzagline->line_width);
170 static void
171 zigzagline_select(Zigzagline *zigzagline, Point *clicked_point,
172 Renderer *interactive_renderer)
174 orthconn_update_data(&zigzagline->orth);
177 static void
178 zigzagline_move_handle(Zigzagline *zigzagline, Handle *handle,
179 Point *to, HandleMoveReason reason, ModifierKeys modifiers)
181 assert(zigzagline!=NULL);
182 assert(handle!=NULL);
183 assert(to!=NULL);
185 orthconn_move_handle(&zigzagline->orth, handle, to, reason);
186 zigzagline_update_data(zigzagline);
190 static void
191 zigzagline_move(Zigzagline *zigzagline, Point *to)
193 orthconn_move(&zigzagline->orth, to);
194 zigzagline_update_data(zigzagline);
197 static void
198 zigzagline_draw(Zigzagline *zigzagline, Renderer *renderer)
200 OrthConn *orth = &zigzagline->orth;
201 Point *points;
202 int n;
204 points = &orth->points[0];
205 n = orth->numpoints;
207 renderer->ops->set_linewidth(renderer, zigzagline->line_width);
208 renderer->ops->set_linestyle(renderer, zigzagline->line_style);
209 renderer->ops->set_dashlength(renderer, zigzagline->dashlength);
210 renderer->ops->set_linejoin(renderer, LINEJOIN_MITER);
211 renderer->ops->set_linecaps(renderer, LINECAPS_BUTT);
213 renderer->ops->draw_polyline(renderer, points, n, &zigzagline->line_color);
215 if (zigzagline->start_arrow.type != ARROW_NONE) {
216 arrow_draw(renderer, zigzagline->start_arrow.type,
217 &points[0], &points[1],
218 zigzagline->start_arrow.length, zigzagline->start_arrow.width,
219 zigzagline->line_width,
220 &zigzagline->line_color, &color_white);
222 if (zigzagline->end_arrow.type != ARROW_NONE) {
223 arrow_draw(renderer, zigzagline->end_arrow.type,
224 &points[n-1], &points[n-2],
225 zigzagline->end_arrow.length, zigzagline->end_arrow.width,
226 zigzagline->line_width,
227 &zigzagline->line_color, &color_white);
231 static Object *
232 zigzagline_create(Point *startpoint,
233 void *user_data,
234 Handle **handle1,
235 Handle **handle2)
237 Zigzagline *zigzagline;
238 OrthConn *orth;
239 Object *obj;
241 /*zigzagline_init_defaults();*/
242 zigzagline = g_malloc0(sizeof(Zigzagline));
243 orth = &zigzagline->orth;
244 obj = &orth->object;
246 obj->type = &zigzagline_type;
247 obj->ops = &zigzagline_ops;
249 orthconn_init(orth, startpoint);
251 zigzagline_update_data(zigzagline);
253 zigzagline->line_width = attributes_get_default_linewidth();
254 zigzagline->line_color = attributes_get_foreground();
255 attributes_get_default_line_style(&zigzagline->line_style,
256 &zigzagline->dashlength);
257 zigzagline->start_arrow = attributes_get_default_start_arrow();
258 zigzagline->end_arrow = attributes_get_default_end_arrow();
260 *handle1 = orth->handles[0];
261 *handle2 = orth->handles[orth->numpoints-2];
262 return &zigzagline->orth.object;
265 static void
266 zigzagline_destroy(Zigzagline *zigzagline)
268 orthconn_destroy(&zigzagline->orth);
271 static Object *
272 zigzagline_copy(Zigzagline *zigzagline)
274 Zigzagline *newzigzagline;
275 OrthConn *orth, *neworth;
276 Object *newobj;
278 orth = &zigzagline->orth;
280 newzigzagline = g_malloc0(sizeof(Zigzagline));
281 neworth = &newzigzagline->orth;
282 newobj = &neworth->object;
284 orthconn_copy(orth, neworth);
286 newzigzagline->line_color = zigzagline->line_color;
287 newzigzagline->line_width = zigzagline->line_width;
288 newzigzagline->line_style = zigzagline->line_style;
289 newzigzagline->dashlength = zigzagline->dashlength;
290 newzigzagline->start_arrow = zigzagline->start_arrow;
291 newzigzagline->end_arrow = zigzagline->end_arrow;
293 return &newzigzagline->orth.object;
296 static void
297 zigzagline_update_data(Zigzagline *zigzagline)
299 OrthConn *orth = &zigzagline->orth;
300 PolyBBExtras *extra = &orth->extra_spacing;
302 orthconn_update_data(&zigzagline->orth);
304 extra->start_long =
305 extra->end_long =
306 extra->middle_trans = zigzagline->line_width/2.0;
307 extra->start_trans = (zigzagline->line_width / 2.0);
308 extra->end_trans = (zigzagline->line_width / 2.0);
310 if (zigzagline->start_arrow.type != ARROW_NONE)
311 extra->start_trans = MAX(extra->start_trans,zigzagline->start_arrow.width);
312 if (zigzagline->end_arrow.type != ARROW_NONE)
313 extra->end_trans = MAX(extra->end_trans,zigzagline->end_arrow.width);
315 orthconn_update_boundingbox(orth);
318 static ObjectChange *
319 zigzagline_add_segment_callback(Object *obj, Point *clicked, gpointer data)
321 ObjectChange *change;
322 change = orthconn_add_segment((OrthConn *)obj, clicked);
323 zigzagline_update_data((Zigzagline *)obj);
324 return change;
327 static ObjectChange *
328 zigzagline_delete_segment_callback(Object *obj, Point *clicked, gpointer data)
330 ObjectChange *change;
331 change = orthconn_delete_segment((OrthConn *)obj, clicked);
332 zigzagline_update_data((Zigzagline *)obj);
333 return change;
336 static DiaMenuItem object_menu_items[] = {
337 { N_("Add segment"), zigzagline_add_segment_callback, NULL, 1 },
338 { N_("Delete segment"), zigzagline_delete_segment_callback, NULL, 1 },
341 static DiaMenu object_menu = {
342 "Zigzagline",
343 sizeof(object_menu_items)/sizeof(DiaMenuItem),
344 object_menu_items,
345 NULL
348 static DiaMenu *
349 zigzagline_get_object_menu(Zigzagline *zigzagline, Point *clickedpoint)
351 OrthConn *orth;
353 orth = &zigzagline->orth;
354 /* Set entries sensitive/selected etc here */
355 object_menu_items[0].active = orthconn_can_add_segment(orth, clickedpoint);
356 object_menu_items[1].active = orthconn_can_delete_segment(orth, clickedpoint);
357 return &object_menu;
361 static void
362 zigzagline_save(Zigzagline *zigzagline, ObjectNode obj_node,
363 const char *filename)
365 orthconn_save(&zigzagline->orth, obj_node);
367 if (!color_equals(&zigzagline->line_color, &color_black))
368 data_add_color(new_attribute(obj_node, "line_color"),
369 &zigzagline->line_color);
371 if (zigzagline->line_width != 0.1)
372 data_add_real(new_attribute(obj_node, "line_width"),
373 zigzagline->line_width);
375 if (zigzagline->line_style != LINESTYLE_SOLID)
376 data_add_enum(new_attribute(obj_node, "line_style"),
377 zigzagline->line_style);
379 if (zigzagline->start_arrow.type != ARROW_NONE) {
380 data_add_enum(new_attribute(obj_node, "start_arrow"),
381 zigzagline->start_arrow.type);
382 data_add_real(new_attribute(obj_node, "start_arrow_length"),
383 zigzagline->start_arrow.length);
384 data_add_real(new_attribute(obj_node, "start_arrow_width"),
385 zigzagline->start_arrow.width);
388 if (zigzagline->end_arrow.type != ARROW_NONE) {
389 data_add_enum(new_attribute(obj_node, "end_arrow"),
390 zigzagline->end_arrow.type);
391 data_add_real(new_attribute(obj_node, "end_arrow_length"),
392 zigzagline->end_arrow.length);
393 data_add_real(new_attribute(obj_node, "end_arrow_width"),
394 zigzagline->end_arrow.width);
397 if (zigzagline->line_style != LINESTYLE_SOLID &&
398 zigzagline->dashlength != DEFAULT_LINESTYLE_DASHLEN)
399 data_add_real(new_attribute(obj_node, "dashlength"),
400 zigzagline->dashlength);
403 static Object *
404 zigzagline_load(ObjectNode obj_node, int version, const char *filename)
406 Zigzagline *zigzagline;
407 OrthConn *orth;
408 Object *obj;
409 AttributeNode attr;
411 zigzagline = g_malloc0(sizeof(Zigzagline));
413 orth = &zigzagline->orth;
414 obj = &orth->object;
416 obj->type = &zigzagline_type;
417 obj->ops = &zigzagline_ops;
419 orthconn_load(orth, obj_node);
421 zigzagline->line_color = color_black;
422 attr = object_find_attribute(obj_node, "line_color");
423 if (attr != NULL)
424 data_color(attribute_first_data(attr), &zigzagline->line_color);
426 zigzagline->line_width = 0.1;
427 attr = object_find_attribute(obj_node, "line_width");
428 if (attr != NULL)
429 zigzagline->line_width = data_real(attribute_first_data(attr));
431 zigzagline->line_style = LINESTYLE_SOLID;
432 attr = object_find_attribute(obj_node, "line_style");
433 if (attr != NULL)
434 zigzagline->line_style = data_enum(attribute_first_data(attr));
436 zigzagline->start_arrow.type = ARROW_NONE;
437 zigzagline->start_arrow.length = 0.8;
438 zigzagline->start_arrow.width = 0.8;
439 attr = object_find_attribute(obj_node, "start_arrow");
440 if (attr != NULL)
441 zigzagline->start_arrow.type = data_enum(attribute_first_data(attr));
442 attr = object_find_attribute(obj_node, "start_arrow_length");
443 if (attr != NULL)
444 zigzagline->start_arrow.length = data_real(attribute_first_data(attr));
445 attr = object_find_attribute(obj_node, "start_arrow_width");
446 if (attr != NULL)
447 zigzagline->start_arrow.width = data_real(attribute_first_data(attr));
449 zigzagline->end_arrow.type = ARROW_NONE;
450 zigzagline->end_arrow.length = 0.8;
451 zigzagline->end_arrow.width = 0.8;
452 attr = object_find_attribute(obj_node, "end_arrow");
453 if (attr != NULL)
454 zigzagline->end_arrow.type = data_enum(attribute_first_data(attr));
455 attr = object_find_attribute(obj_node, "end_arrow_length");
456 if (attr != NULL)
457 zigzagline->end_arrow.length = data_real(attribute_first_data(attr));
458 attr = object_find_attribute(obj_node, "end_arrow_width");
459 if (attr != NULL)
460 zigzagline->end_arrow.width = data_real(attribute_first_data(attr));
462 zigzagline->dashlength = DEFAULT_LINESTYLE_DASHLEN;
463 attr = object_find_attribute(obj_node, "dashlength");
464 if (attr != NULL)
465 zigzagline->dashlength = data_real(attribute_first_data(attr));
467 zigzagline_update_data(zigzagline);
469 return &zigzagline->orth.object;