/* Dia -- an diagram creation/manipulation program * Copyright (C) 1998 Alexander Larsson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* DO NOT USE THIS OBJECT AS A BASIS FOR A NEW OBJECT. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "intl.h" #include "object.h" #include "orth_conn.h" #include "diarenderer.h" #include "attributes.h" #include "arrows.h" #include "properties.h" #include "pixmaps/participation.xpm" typedef struct _Participation Participation; struct _Participation { OrthConn orth; gboolean total; }; #define PARTICIPATION_WIDTH 0.1 #define PARTICIPATION_DASHLEN 0.4 #define PARTICIPATION_FONTHEIGHT 0.8 #define TOTAL_SEPARATION 0.25 static real participation_distance_from(Participation *dep, Point *point); static void participation_select(Participation *dep, Point *clicked_point, DiaRenderer *interactive_renderer); static ObjectChange* participation_move_handle(Participation *dep, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers); static ObjectChange* participation_move(Participation *dep, Point *to); static void participation_draw(Participation *dep, DiaRenderer *renderer); static DiaObject *participation_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2); static DiaObject *participation_copy(Participation *dep); static void participation_save(Participation *dep, ObjectNode obj_node, const char *filename); static DiaObject *participation_load(ObjectNode obj_node, int version, const char *filename); static void participation_update_data(Participation *dep); static PropDescription * participation_describe_props(Participation *participation); static void participation_get_props(Participation *participation, GPtrArray *props); static void participation_set_props(Participation *participation, GPtrArray *props); static DiaMenu *participation_get_object_menu(Participation *participation, Point *clickedpoint); static ObjectTypeOps participation_type_ops = { (CreateFunc) participation_create, (LoadFunc) participation_load, (SaveFunc) participation_save }; DiaObjectType participation_type = { "ER - Participation", /* name */ /* Version 0 had no autorouting and so shouldn't have it set by default. */ 1, /* version */ (char **) participation_xpm, /* pixmap */ &participation_type_ops /* ops */ }; static ObjectOps participation_ops = { (DestroyFunc) orthconn_destroy, (DrawFunc) participation_draw, (DistanceFunc) participation_distance_from, (SelectFunc) participation_select, (CopyFunc) participation_copy, (MoveFunc) participation_move, (MoveHandleFunc) participation_move_handle, (GetPropertiesFunc) object_create_props_dialog, (ApplyPropertiesFunc) object_apply_props_from_dialog, (ObjectMenuFunc) participation_get_object_menu, (DescribePropsFunc) participation_describe_props, (GetPropsFunc) participation_get_props, (SetPropsFunc) participation_set_props }; static PropDescription participation_props[] = { ORTHCONN_COMMON_PROPERTIES, { "total", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE, N_("Total:"), NULL, NULL }, PROP_DESC_END }; static PropDescription * participation_describe_props(Participation *participation) { if (participation_props[0].quark == 0) prop_desc_list_calculate_quarks(participation_props); return participation_props; } static PropOffset participation_offsets[] = { ORTHCONN_COMMON_PROPERTIES_OFFSETS, { "total", PROP_TYPE_BOOL, offsetof(Participation, total) }, { NULL, 0, 0} }; static void participation_get_props(Participation *participation, GPtrArray *props) { object_get_props_from_offsets(&participation->orth.object, participation_offsets, props); } static void participation_set_props(Participation *participation, GPtrArray *props) { object_set_props_from_offsets(&participation->orth.object, participation_offsets, props); participation_update_data(participation); } static real participation_distance_from(Participation *participation, Point *point) { OrthConn *orth = &participation->orth; return orthconn_distance_from(orth, point, PARTICIPATION_WIDTH); } static void participation_select(Participation *participation, Point *clicked_point, DiaRenderer *interactive_renderer) { orthconn_update_data(&participation->orth); } static ObjectChange* participation_move_handle(Participation *participation, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { ObjectChange *change; assert(participation!=NULL); assert(handle!=NULL); assert(to!=NULL); change = orthconn_move_handle(&participation->orth, handle, to, cp, reason, modifiers); participation_update_data(participation); return change; } static ObjectChange* participation_move(Participation *participation, Point *to) { ObjectChange *change; change = orthconn_move(&participation->orth, to); participation_update_data(participation); return change; } static void participation_draw(Participation *participation, DiaRenderer *renderer) { DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer); OrthConn *orth = &participation->orth; Point *points; Point *left_points; Point *right_points; int i, n; real last_left, last_right; points = &orth->points[0]; n = orth->numpoints; last_left = 0.0; last_right = 0.0; renderer_ops->set_linewidth(renderer, PARTICIPATION_WIDTH); renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID); renderer_ops->set_linejoin(renderer, LINEJOIN_MITER); renderer_ops->set_linecaps(renderer, LINECAPS_BUTT); if (participation->total) { left_points = g_new0(Point, n); right_points = g_new0(Point, n); for(i = 0; i < n - 1; i++) { if(orth->orientation[i] == HORIZONTAL) { /* HORIZONTAL */ if (points[i].x < points[i+1].x) { /* RIGHT */ left_points[i].x = points[i].x + last_left; left_points[i].y = points[i].y - TOTAL_SEPARATION / 2.0; last_left = - TOTAL_SEPARATION/2.0; right_points[i].x = points[i].x + last_right; right_points[i].y = points[i].y + TOTAL_SEPARATION / 2.0; last_right = TOTAL_SEPARATION/2.0; } else { /* LEFT */ left_points[i].x = points[i].x + last_left; left_points[i].y = points[i].y + TOTAL_SEPARATION / 2.0; last_left = TOTAL_SEPARATION/2.0; right_points[i].x = points[i].x + last_right; right_points[i].y = points[i].y - TOTAL_SEPARATION / 2.0; last_right = - TOTAL_SEPARATION/2.0; } } else { /* VERTICAL */ if (points[i].y < points[i+1].y) { /* DOWN */ left_points[i].x = points[i].x + TOTAL_SEPARATION / 2.0; left_points[i].y = points[i].y + last_left; last_left = TOTAL_SEPARATION/2.0; right_points[i].x = points[i].x - TOTAL_SEPARATION / 2.0; right_points[i].y = points[i].y + last_right; last_right = - TOTAL_SEPARATION/2.0; } else { /* UP */ left_points[i].x = points[i].x - TOTAL_SEPARATION / 2.0; left_points[i].y = points[i].y + last_left; last_left = - TOTAL_SEPARATION/2.0; right_points[i].x = points[i].x + TOTAL_SEPARATION / 2.0; right_points[i].y = points[i].y + last_right; last_right = TOTAL_SEPARATION/2.0; } } } if(orth->orientation[i-1] == HORIZONTAL) { /* HORIZONTAL */ left_points[i].x = points[i].x; left_points[i].y = points[i].y + last_left; right_points[i].x = points[i].x; right_points[i].y = points[i].y + last_right; } else { /* VERTICAL */ left_points[i].x = points[i].x + last_left; left_points[i].y = points[i].y; right_points[i].x = points[i].x + last_right; right_points[i].y = points[i].y; } renderer_ops->draw_polyline(renderer, left_points, n, &color_black); renderer_ops->draw_polyline(renderer, right_points, n, &color_black); g_free(left_points); g_free(right_points); } else { renderer_ops->draw_polyline(renderer, points, n, &color_black); } } static void participation_update_data(Participation *participation) { OrthConn *orth = &participation->orth; PolyBBExtras *extra = &orth->extra_spacing; real extra_width; orthconn_update_data(orth); if (participation->total) { extra_width = TOTAL_SEPARATION/2.0; } else { extra_width = 0.0; } extra->middle_trans = extra->start_trans = extra->end_trans = extra->start_long = extra->end_long = PARTICIPATION_WIDTH/2.0 + extra_width; orthconn_update_boundingbox(orth); } static DiaObject * participation_create(Point *startpoint, void *user_data, Handle **handle1, Handle **handle2) { Participation *participation; OrthConn *orth; DiaObject *obj; participation = g_malloc0(sizeof(Participation)); orth = &participation->orth; obj = &orth->object; obj->type = &participation_type; obj->ops = &participation_ops; orthconn_init(orth, startpoint); participation_update_data(participation); participation->total = FALSE; *handle1 = orth->handles[0]; *handle2 = orth->handles[orth->numpoints-2]; return &participation->orth.object; } static DiaObject * participation_copy(Participation *participation) { Participation *newparticipation; OrthConn *orth, *neworth; DiaObject *newobj; orth = &participation->orth; newparticipation = g_malloc0(sizeof(Participation)); neworth = &newparticipation->orth; newobj = &neworth->object; orthconn_copy(orth, neworth); newparticipation->total = participation->total; participation_update_data(newparticipation); return &newparticipation->orth.object; } static void participation_save(Participation *participation, ObjectNode obj_node, const char *filename) { orthconn_save(&participation->orth, obj_node); data_add_boolean(new_attribute(obj_node, "total"), participation->total); } static DiaObject * participation_load(ObjectNode obj_node, int version, const char *filename) { AttributeNode attr; Participation *participation; OrthConn *orth; DiaObject *obj; participation = g_new0(Participation, 1); orth = &participation->orth; obj = &orth->object; obj->type = &participation_type; obj->ops = &participation_ops; orthconn_load(orth, obj_node); attr = object_find_attribute(obj_node, "total"); if (attr != NULL) participation->total = data_boolean(attribute_first_data(attr)); participation_update_data(participation); return &participation->orth.object; } static ObjectChange * participation_add_segment_callback(DiaObject *obj, Point *clicked, gpointer data) { ObjectChange *change; change = orthconn_add_segment((OrthConn *)obj, clicked); participation_update_data((Participation *)obj); return change; } static ObjectChange * participation_delete_segment_callback(DiaObject *obj, Point *clicked, gpointer data) { ObjectChange *change; change = orthconn_delete_segment((OrthConn *)obj, clicked); participation_update_data((Participation *)obj); return change; } static DiaMenuItem object_menu_items[] = { { N_("Add segment"), participation_add_segment_callback, NULL, 1 }, { N_("Delete segment"), participation_delete_segment_callback, NULL, 1 }, ORTHCONN_COMMON_MENUS, }; static DiaMenu object_menu = { "Participation", sizeof(object_menu_items)/sizeof(DiaMenuItem), object_menu_items, NULL }; static DiaMenu * participation_get_object_menu(Participation *participation, Point *clickedpoint) { OrthConn *orth; orth = &participation->orth; /* Set entries sensitive/selected etc here */ object_menu_items[0].active = orthconn_can_add_segment(orth, clickedpoint); object_menu_items[1].active = orthconn_can_delete_segment(orth, clickedpoint); orthconn_update_object_menu(orth, clickedpoint, &object_menu_items[2]); return &object_menu; }