1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998, 1999 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 /* If you have a problem with the Function Structure (FS) components,
20 * please send e-mail to David Thompson <dcthomp@mail.utexas.edu>
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <assert.h>
28 #include <math.h>
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "intl.h"
33 #include "object.h"
34 #include "objchange.h"
35 #include "connection.h"
36 #include "diarenderer.h"
37 #include "handle.h"
38 #include "arrows.h"
39 #include "diamenu.h"
40 #include "text.h"
41 #include "orth_conn.h"
42 #include "element.h"
43 #include "properties.h"
44
45 #include "pixmaps/orthflow.xpm"
46
47
48 typedef struct _Orthflow Orthflow;
49 typedef struct _OrthflowChange OrthflowChange;
50
51 typedef enum {
52 ORTHFLOW_ENERGY,
53 ORTHFLOW_MATERIAL,
54 ORTHFLOW_SIGNAL
55 } OrthflowType;
56
57 struct _Orthflow {
58 OrthConn orth ;
59
60 Handle text_handle;
61
62 Text* text;
63 TextAttributes attrs;
64 OrthflowType type;
65 Point textpos; /* This is the master position, only overridden in load */
66 };
67
68 enum OrthflowChangeType {
69 TEXT_EDIT=1,
70 FLOW_TYPE=2,
71 BOTH=3
72 };
73
74 struct _OrthflowChange {
75 ObjectChange obj_change ;
76 enum OrthflowChangeType change_type ;
77 OrthflowType type ;
78 char* text ;
79 };
80
81 Color orthflow_color_energy = { 1.0f, 0.0f, 0.0f };
82 Color orthflow_color_material = { 0.8f, 0.0f, 0.8f };
83 Color orthflow_color_signal = { 0.0f, 0.0f, 1.0f };
84
85
86 #define ORTHFLOW_WIDTH 0.1
87 #define ORTHFLOW_MATERIAL_WIDTH 0.2
88 #define ORTHFLOW_DASHLEN 0.4
89 #define ORTHFLOW_FONTHEIGHT 0.6
90 #define ORTHFLOW_ARROWLEN 0.8
91 #define ORTHFLOW_ARROWWIDTH 0.5
92 #define HANDLE_MOVE_TEXT (HANDLE_CUSTOM2)
93
94 static ObjectChange* orthflow_move_handle(Orthflow *orthflow, Handle *handle,
95 Point *to, ConnectionPoint *cp,
96 HandleMoveReason reason,
97 ModifierKeys modifiers);
98 static ObjectChange* orthflow_move(Orthflow *orthflow, Point *to);
99 static void orthflow_select(Orthflow *orthflow, Point *clicked_point,
100 DiaRenderer *interactive_renderer);
101 static void orthflow_draw(Orthflow *orthflow, DiaRenderer *renderer);
102 static DiaObject *orthflow_create(Point *startpoint,
103 void *user_data,
104 Handle **handle1,
105 Handle **handle2);
106 static real orthflow_distance_from(Orthflow *orthflow, Point *point);
107 static void orthflow_update_data(Orthflow *orthflow);
108 static void orthflow_destroy(Orthflow *orthflow);
109 static DiaObject *orthflow_copy(Orthflow *orthflow);
110 static PropDescription *orthflow_describe_props(Orthflow *mes);
111 static void
112 orthflow_get_props(Orthflow * orthflow, GPtrArray *props);
113 static void
114 orthflow_set_props(Orthflow * orthflow, GPtrArray *props);
115 static void orthflow_save(Orthflow *orthflow, ObjectNode obj_node,
116 const char *filename);
117 static DiaObject *orthflow_load(ObjectNode obj_node, int version,
118 const char *filename);
119 static DiaMenu *orthflow_get_object_menu(Orthflow *orthflow, Point *clickedpoint) ;
120
121
122 static ObjectTypeOps orthflow_type_ops =
123 {
124 (CreateFunc) orthflow_create,
125 (LoadFunc) orthflow_load,
126 (SaveFunc) orthflow_save,
127 (GetDefaultsFunc) NULL,
128 (ApplyDefaultsFunc) NULL,
129
130 } ;
131
132 DiaObjectType orthflow_type =
133 {
134 "FS - Orthflow", /* name */
135 /* Version 0 had no autorouting and so shouldn't have it set by default. */
136 1, /* version */
137 (char **) orthflow_xpm, /* pixmap */
138 &orthflow_type_ops /* ops */
139 };
140
141 static ObjectOps orthflow_ops = {
142 (DestroyFunc) orthflow_destroy,
143 (DrawFunc) orthflow_draw,
144 (DistanceFunc) orthflow_distance_from,
145 (SelectFunc) orthflow_select,
146 (CopyFunc) orthflow_copy,
147 (MoveFunc) orthflow_move,
148 (MoveHandleFunc) orthflow_move_handle,
149 (GetPropertiesFunc) object_create_props_dialog,
150 (ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
151 (ObjectMenuFunc) orthflow_get_object_menu,
152 (DescribePropsFunc) orthflow_describe_props,
153 (GetPropsFunc) orthflow_get_props,
154 (SetPropsFunc) orthflow_set_props,
155 (TextEditFunc) 0,
156 (ApplyPropertiesListFunc) object_apply_props,
157 };
158
159 static PropEnumData prop_orthflow_type_data[] = {
160 { N_("Energy"),ORTHFLOW_ENERGY },
161 { N_("Material"),ORTHFLOW_MATERIAL },
162 { N_("Signal"),ORTHFLOW_SIGNAL },
163 { NULL, 0 }
164 };
165
166 static PropDescription orthflow_props[] = {
167 ELEMENT_COMMON_PROPERTIES,
168 { "type", PROP_TYPE_ENUM, PROP_FLAG_VISIBLE,
169 N_("Type:"), NULL, prop_orthflow_type_data },
170 { "text", PROP_TYPE_TEXT, 0, NULL, NULL },
171 PROP_STD_TEXT_ALIGNMENT,
172 PROP_STD_TEXT_FONT,
173 PROP_STD_TEXT_HEIGHT,
174 /* Colour determined from type, don't show */
175 { "text_colour", PROP_TYPE_COLOUR, PROP_FLAG_DONT_SAVE, },
176 PROP_DESC_END
177 };
178
179 static PropDescription *
orthflow_describe_props(Orthflow * mes)180 orthflow_describe_props(Orthflow *mes)
181 {
182 if (orthflow_props[0].quark == 0)
183 prop_desc_list_calculate_quarks(orthflow_props);
184 return orthflow_props;
185
186 }
187
188 static PropOffset orthflow_offsets[] = {
189 OBJECT_COMMON_PROPERTIES_OFFSETS,
190 { "type", PROP_TYPE_ENUM, offsetof(Orthflow, type) },
191 { "text", PROP_TYPE_TEXT, offsetof (Orthflow, text) },
192 { "text_alignment", PROP_TYPE_ENUM, offsetof (Orthflow, attrs.alignment) },
193 { "text_font", PROP_TYPE_FONT, offsetof (Orthflow, attrs.font) },
194 { PROP_STDNAME_TEXT_HEIGHT, PROP_STDTYPE_TEXT_HEIGHT, offsetof (Orthflow, attrs.height) },
195 { "text_colour", PROP_TYPE_COLOUR, offsetof (Orthflow, attrs.color) },
196 { NULL, 0, 0 }
197 };
198
199 static void
orthflow_get_props(Orthflow * orthflow,GPtrArray * props)200 orthflow_get_props(Orthflow * orthflow, GPtrArray *props)
201 {
202 text_get_attributes (orthflow->text, &orthflow->attrs);
203 object_get_props_from_offsets(&orthflow->orth.object,
204 orthflow_offsets, props);
205 }
206
207 static void
orthflow_set_props(Orthflow * orthflow,GPtrArray * props)208 orthflow_set_props(Orthflow *orthflow, GPtrArray *props)
209 {
210 object_set_props_from_offsets(&orthflow->orth.object,
211 orthflow_offsets, props);
212 apply_textattr_properties (props, orthflow->text, "text", &orthflow->attrs);
213 orthflow_update_data(orthflow);
214 }
215
216
217
218 static void
orthflow_change_apply_revert(ObjectChange * objchg,DiaObject * obj)219 orthflow_change_apply_revert(ObjectChange* objchg, DiaObject* obj)
220 {
221 struct _OrthflowChange* change = (struct _OrthflowChange*) objchg ;
222 Orthflow* oflow = (Orthflow*) obj ;
223
224 if ( change->change_type == FLOW_TYPE || change->change_type == BOTH ) {
225 OrthflowType type = oflow->type ;
226 oflow->type = change->type ;
227 change->type = type ;
228 orthflow_update_data(oflow) ;
229 }
230
231 if ( change->change_type & TEXT_EDIT || change->change_type == BOTH ) {
232 char* tmp = text_get_string_copy( oflow->text ) ;
233 text_set_string( oflow->text, change->text ) ;
234 g_free( change->text ) ;
235 change->text = tmp ;
236 }
237 }
238
239 static void
orthflow_change_free(ObjectChange * objchg)240 orthflow_change_free(ObjectChange* objchg)
241 {
242 struct _OrthflowChange* change = (struct _OrthflowChange*) objchg ;
243
244 if (change->change_type & TEXT_EDIT || change->change_type == BOTH ) {
245 g_free(change->text) ;
246 }
247 }
248
249 static ObjectChange*
orthflow_create_change(enum OrthflowChangeType change_type,OrthflowType type,Text * text)250 orthflow_create_change( enum OrthflowChangeType change_type,
251 OrthflowType type, Text* text )
252 {
253 struct _OrthflowChange* change ;
254 change = g_new0( struct _OrthflowChange, 1 ) ;
255 change->obj_change.apply = (ObjectChangeApplyFunc) orthflow_change_apply_revert ;
256 change->obj_change.revert = (ObjectChangeRevertFunc) orthflow_change_apply_revert ;
257 change->obj_change.free = (ObjectChangeFreeFunc) orthflow_change_free ;
258 change->change_type = change_type ;
259
260 change->type = type ;
261 if ( text ) {
262 change->text = text_get_string_copy( text ) ;
263 }
264
265 return (ObjectChange*) change ;
266 }
267
268 static real
orthflow_distance_from(Orthflow * orthflow,Point * point)269 orthflow_distance_from(Orthflow *orthflow, Point *point)
270 {
271 real linedist;
272 real textdist;
273
274 linedist = orthconn_distance_from( &orthflow->orth, point,
275 orthflow->type == ORTHFLOW_MATERIAL ?
276 ORTHFLOW_MATERIAL_WIDTH :
277 ORTHFLOW_WIDTH ) ;
278 textdist = text_distance_from( orthflow->text, point ) ;
279
280 return linedist > textdist ? textdist : linedist ;
281 }
282
283 static void
orthflow_select(Orthflow * orthflow,Point * clicked_point,DiaRenderer * interactive_renderer)284 orthflow_select(Orthflow *orthflow, Point *clicked_point,
285 DiaRenderer *interactive_renderer)
286 {
287 text_set_cursor(orthflow->text, clicked_point, interactive_renderer);
288 text_grab_focus(orthflow->text, &orthflow->orth.object);
289
290 orthconn_update_data(&orthflow->orth);
291 }
292
293 static ObjectChange*
orthflow_move_handle(Orthflow * orthflow,Handle * handle,Point * to,ConnectionPoint * cp,HandleMoveReason reason,ModifierKeys modifiers)294 orthflow_move_handle(Orthflow *orthflow, Handle *handle,
295 Point *to, ConnectionPoint *cp,
296 HandleMoveReason reason, ModifierKeys modifiers)
297 {
298 ObjectChange *change = NULL;
299 assert(orthflow!=NULL);
300 assert(handle!=NULL);
301 assert(to!=NULL);
302
303 if (handle->id == HANDLE_MOVE_TEXT) {
304 orthflow->textpos = *to;
305 } else {
306 Point along ;
307
308 along = orthflow->textpos ;
309 point_sub( &along, &(orthconn_get_middle_handle(&orthflow->orth)->pos) ) ;
310
311 change = orthconn_move_handle( &orthflow->orth, handle, to, cp,
312 reason, modifiers);
313 orthconn_update_data( &orthflow->orth ) ;
314
315 orthflow->textpos = orthconn_get_middle_handle(&orthflow->orth)->pos ;
316 point_add( &orthflow->textpos, &along ) ;
317 }
318
319 orthflow_update_data(orthflow);
320
321 return change;
322 }
323
324 static ObjectChange*
orthflow_move(Orthflow * orthflow,Point * to)325 orthflow_move(Orthflow *orthflow, Point *to)
326 {
327 ObjectChange *change;
328
329 Point *points = &orthflow->orth.points[0];
330 Point delta;
331
332 delta = *to;
333 point_sub(&delta, &points[0]);
334 point_add(&orthflow->textpos, &delta);
335
336 change = orthconn_move( &orthflow->orth, to ) ;
337
338 orthflow_update_data(orthflow);
339
340 return change;
341 }
342
343 static void
orthflow_draw(Orthflow * orthflow,DiaRenderer * renderer)344 orthflow_draw(Orthflow *orthflow, DiaRenderer *renderer)
345 {
346 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
347 int n = orthflow->orth.numpoints ;
348 Color* render_color = &orthflow_color_signal;
349 Point *points;
350 real linewidth;
351 Arrow arrow;
352
353 assert(orthflow != NULL);
354 assert(renderer != NULL);
355
356 arrow.type = ARROW_FILLED_TRIANGLE;
357 arrow.width = ORTHFLOW_ARROWWIDTH;
358 arrow.length = ORTHFLOW_ARROWLEN;
359
360 points = &orthflow->orth.points[0];
361
362 renderer_ops->set_linecaps(renderer, LINECAPS_BUTT);
363
364 switch (orthflow->type) {
365 case ORTHFLOW_SIGNAL:
366 linewidth = ORTHFLOW_WIDTH;
367 renderer_ops->set_dashlength(renderer, ORTHFLOW_DASHLEN);
368 renderer_ops->set_linestyle(renderer, LINESTYLE_DASHED);
369 render_color = &orthflow_color_signal ;
370 break ;
371 case ORTHFLOW_MATERIAL:
372 linewidth = ORTHFLOW_MATERIAL_WIDTH;
373 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
374 render_color = &orthflow_color_material ;
375 break ;
376 case ORTHFLOW_ENERGY:
377 linewidth = ORTHFLOW_WIDTH;
378 renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
379 render_color = &orthflow_color_energy ;
380 break ;
381 default:
382 linewidth = 0.001;
383 break;
384 }
385
386 renderer_ops->set_linewidth(renderer, linewidth);
387 renderer_ops->draw_polyline_with_arrows(renderer, points, n,
388 ORTHFLOW_WIDTH,
389 render_color,
390 NULL, &arrow);
391
392 text_draw(orthflow->text, renderer);
393 }
394
395 static DiaObject *
orthflow_create(Point * startpoint,void * user_data,Handle ** handle1,Handle ** handle2)396 orthflow_create(Point *startpoint,
397 void *user_data,
398 Handle **handle1,
399 Handle **handle2)
400 {
401 Orthflow *orthflow;
402 OrthConn *orth;
403 DiaObject *obj;
404 Point p;
405 PolyBBExtras *extra;
406 DiaFont *font;
407
408 orthflow = g_new0(Orthflow,1);
409 orth = &orthflow->orth ;
410 orthconn_init( orth, startpoint ) ;
411
412 obj = &orth->object;
413 extra = &orth->extra_spacing;
414
415 obj->type = &orthflow_type;
416 obj->ops = &orthflow_ops;
417
418 /* Where to put the text */
419 p = *startpoint ;
420 p.y += 0.1 * ORTHFLOW_FONTHEIGHT ;
421 orthflow->textpos = p;
422 font = dia_font_new_from_style(DIA_FONT_SANS, 0.8);
423
424 orthflow->text = new_text("", font, 0.8, &p, &color_black, ALIGN_CENTER);
425 dia_font_unref(font);
426 text_get_attributes(orthflow->text, &orthflow->attrs);
427
428 #if 0
429 if ( orthflow_default_label ) {
430 orthflow->text = text_copy( orthflow_default_label ) ;
431 text_set_position( orthflow->text, &p ) ;
432 } else {
433 Color* color = &orthflow_color_signal;
434
435 switch (orthflow->type) {
436 case ORTHFLOW_ENERGY:
437 color = &orthflow_color_energy ;
438 break ;
439 case ORTHFLOW_MATERIAL:
440 color = &orthflow_color_material ;
441 break ;
442 case ORTHFLOW_SIGNAL:
443 color = &orthflow_color_signal ;
444 break ;
445 }
446
447 }
448 #endif
449
450 orthflow->text_handle.id = HANDLE_MOVE_TEXT;
451 orthflow->text_handle.type = HANDLE_MINOR_CONTROL;
452 orthflow->text_handle.connect_type = HANDLE_NONCONNECTABLE;
453 orthflow->text_handle.connected_to = NULL;
454 object_add_handle( obj, &orthflow->text_handle ) ;
455
456 extra->start_long =
457 extra->start_trans =
458 extra->middle_trans = ORTHFLOW_WIDTH/2.0;
459 extra->end_long =
460 extra->end_trans = ORTHFLOW_WIDTH/2 + ORTHFLOW_ARROWLEN;
461
462 orthflow_update_data(orthflow);
463
464 /*obj->handles[1] = orth->handles[2] ;*/
465 *handle1 = obj->handles[0];
466 *handle2 = obj->handles[1];
467 return &orthflow->orth.object;
468 }
469
470
471 static void
orthflow_destroy(Orthflow * orthflow)472 orthflow_destroy(Orthflow *orthflow)
473 {
474 orthconn_destroy( &orthflow->orth ) ;
475 text_destroy( orthflow->text ) ;
476 }
477
478 static DiaObject *
orthflow_copy(Orthflow * orthflow)479 orthflow_copy(Orthflow *orthflow)
480 {
481 Orthflow *neworthflow;
482 OrthConn *orth, *neworth;
483 DiaObject *newobj;
484
485 orth = &orthflow->orth;
486
487 neworthflow = g_malloc0(sizeof(Orthflow));
488 neworth = &neworthflow->orth;
489 newobj = &neworth->object;
490
491 orthconn_copy(orth, neworth);
492
493 neworthflow->text_handle = orthflow->text_handle;
494 neworthflow->text_handle.connected_to = NULL;
495 newobj->handles[orth->numpoints-1] = &neworthflow->text_handle;
496
497 neworthflow->text = text_copy(orthflow->text);
498 neworthflow->type = orthflow->type;
499
500 orthflow_update_data(neworthflow);
501 return &neworthflow->orth.object;
502 }
503
504
505 static void
orthflow_update_data(Orthflow * orthflow)506 orthflow_update_data(Orthflow *orthflow)
507 {
508 OrthConn *orth = &orthflow->orth ;
509 DiaObject *obj = &orth->object;
510 Rectangle rect;
511 Color* color = &orthflow_color_signal;
512
513 switch (orthflow->type) {
514 case ORTHFLOW_ENERGY:
515 color = &orthflow_color_energy ;
516 break ;
517 case ORTHFLOW_MATERIAL:
518 color = &orthflow_color_material ;
519 break ;
520 case ORTHFLOW_SIGNAL:
521 color = &orthflow_color_signal ;
522 break ;
523 }
524 text_set_color( orthflow->text, color ) ;
525
526 text_set_position( orthflow->text, &orthflow->textpos ) ;
527 orthflow->text_handle.pos = orthflow->textpos;
528
529 orthconn_update_data(orth);
530 obj->position = orth->points[0];
531
532 /* Boundingbox: */
533 orthconn_update_boundingbox(orth);
534
535 /* Add boundingbox for text: */
536 text_calc_boundingbox(orthflow->text, &rect) ;
537 rectangle_union(&obj->bounding_box, &rect);
538 }
539
540
541 static void
orthflow_save(Orthflow * orthflow,ObjectNode obj_node,const char * filename)542 orthflow_save(Orthflow *orthflow, ObjectNode obj_node, const char *filename)
543 {
544 orthconn_save(&orthflow->orth, obj_node);
545
546 data_add_text(new_attribute(obj_node, "text"),
547 orthflow->text) ;
548 data_add_int(new_attribute(obj_node, "type"),
549 orthflow->type);
550 }
551
552 static DiaObject *
orthflow_load(ObjectNode obj_node,int version,const char * filename)553 orthflow_load(ObjectNode obj_node, int version, const char *filename)
554 {
555 Orthflow *orthflow;
556 AttributeNode attr;
557 OrthConn *orth;
558 DiaObject *obj;
559 PolyBBExtras *extra;
560
561 orthflow = g_malloc0(sizeof(Orthflow));
562
563 orth = &orthflow->orth;
564 obj = &orth->object;
565 extra = &orth->extra_spacing;
566
567 obj->type = &orthflow_type;
568 obj->ops = &orthflow_ops;
569
570 orthconn_load(orth, obj_node);
571
572 orthflow->text = NULL;
573 attr = object_find_attribute(obj_node, "text");
574 if (attr != NULL)
575 orthflow->text = data_text(attribute_first_data(attr));
576
577 attr = object_find_attribute(obj_node, "type");
578 if (attr != NULL)
579 orthflow->type = (OrthflowType)data_int(attribute_first_data(attr));
580
581 orthflow->text_handle.id = HANDLE_MOVE_TEXT;
582 orthflow->text_handle.type = HANDLE_MINOR_CONTROL;
583 orthflow->text_handle.connect_type = HANDLE_NONCONNECTABLE;
584 orthflow->text_handle.connected_to = NULL;
585 /* Mein Gott! The extra handle was never added */
586 object_add_handle(obj, &orthflow->text_handle);
587 obj->handles[orth->numpoints-1] = &orthflow->text_handle;
588
589 extra->start_long =
590 extra->start_trans =
591 extra->middle_trans = ORTHFLOW_WIDTH/2.0;
592 extra->end_long =
593 extra->end_trans = ORTHFLOW_WIDTH/2 + ORTHFLOW_ARROWLEN;
594 orthflow->textpos = orthflow->text->position;
595
596 orthflow_update_data(orthflow);
597
598 return &orthflow->orth.object;
599 }
600
601 static ObjectChange *
orthflow_set_type_callback(DiaObject * obj,Point * clicked,gpointer data)602 orthflow_set_type_callback (DiaObject* obj, Point* clicked, gpointer data)
603 {
604 ObjectChange* change ;
605 change = orthflow_create_change( FLOW_TYPE, ((Orthflow*)obj)->type, 0 ) ;
606
607 ((Orthflow*)obj)->type = GPOINTER_TO_INT (data);
608 orthflow_update_data((Orthflow*)obj);
609
610 return change;
611 }
612
613 static ObjectChange *
orthflow_segment_callback(DiaObject * obj,Point * clicked,gpointer data)614 orthflow_segment_callback (DiaObject* obj, Point* clicked, gpointer data)
615 {
616 if ( GPOINTER_TO_INT (data) )
617 return orthconn_add_segment( (OrthConn*)obj, clicked ) ;
618
619 return orthconn_delete_segment( (OrthConn*)obj, clicked ) ;
620 }
621
622 static DiaMenuItem orthflow_menu_items[] = {
623 { N_("Energy"), orthflow_set_type_callback, (void*)ORTHFLOW_ENERGY, 1 },
624 { N_("Material"), orthflow_set_type_callback, (void*)ORTHFLOW_MATERIAL, 1 },
625 { N_("Signal"), orthflow_set_type_callback, (void*)ORTHFLOW_SIGNAL, 1 },
626 { N_("Add segment"), orthflow_segment_callback, (void*)1, 1 },
627 { N_("Delete segment"), orthflow_segment_callback, (void*)0, 1 },
628 ORTHCONN_COMMON_MENUS,
629 };
630
631 static DiaMenu orthflow_menu = {
632 "Orthflow",
633 sizeof(orthflow_menu_items)/sizeof(DiaMenuItem),
634 orthflow_menu_items,
635 NULL
636 };
637
638 static DiaMenu *
orthflow_get_object_menu(Orthflow * orthflow,Point * clickedpoint)639 orthflow_get_object_menu(Orthflow *orthflow, Point *clickedpoint)
640 {
641 orthflow_menu_items[4].active = orthflow->orth.numpoints > 3;
642 orthconn_update_object_menu((OrthConn*)orthflow,
643 clickedpoint, &orthflow_menu_items[5]);
644 return &orthflow_menu;
645 }
646
647
648