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 #include <config.h>
19
20 #include <assert.h>
21
22 #include "connectionpoint_ops.h"
23 #include "object_ops.h"
24 #include "color.h"
25
26 static Color connectionpoint_color = { 0.4, 0.4, 1.0 };
27
28 #define CP_SZ (CONNECTIONPOINT_SIZE/2)
29
30 void
connectionpoint_draw(ConnectionPoint * conpoint,DDisplay * ddisp)31 connectionpoint_draw(ConnectionPoint *conpoint,
32 DDisplay *ddisp)
33 {
34 int x,y;
35 Point *point = &conpoint->pos;
36 DiaRenderer *renderer = ddisp->renderer;
37 DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (ddisp->renderer);
38 DiaInteractiveRendererInterface *irenderer =
39 DIA_GET_INTERACTIVE_RENDERER_INTERFACE (ddisp->renderer);
40
41 /* draw the "whole object"/center connpoints, but only when we don't
42 * have snap-to-grid */
43 if (conpoint->flags & CP_FLAG_ANYPLACE) {
44 if (!ddisp->mainpoint_magnetism) {
45 static Color midpoint_color = { 1.0, 0.0, 0.0 };
46
47 ddisplay_transform_coords(ddisp, point->x, point->y, &x, &y);
48
49 irenderer->draw_pixel_line (renderer,
50 x-CP_SZ,y-CP_SZ,
51 x+CP_SZ,y+CP_SZ,
52 &midpoint_color);
53
54 irenderer->draw_pixel_line (renderer,
55 x+CP_SZ,y-CP_SZ,
56 x-CP_SZ,y+CP_SZ,
57 &midpoint_color);
58 }
59 return;
60 }
61
62 ddisplay_transform_coords(ddisp, point->x, point->y, &x, &y);
63
64 renderer_ops->set_linewidth (renderer, 0.0);
65 renderer_ops->set_linestyle (renderer, LINESTYLE_SOLID);
66
67 irenderer->draw_pixel_line (renderer,
68 x-CP_SZ,y-CP_SZ,
69 x+CP_SZ,y+CP_SZ,
70 &connectionpoint_color);
71
72 irenderer->draw_pixel_line (renderer,
73 x+CP_SZ,y-CP_SZ,
74 x-CP_SZ,y+CP_SZ,
75 &connectionpoint_color);
76 }
77
78 void
connectionpoint_add_update(ConnectionPoint * conpoint,Diagram * dia)79 connectionpoint_add_update(ConnectionPoint *conpoint,
80 Diagram *dia)
81 {
82 diagram_add_update_pixels(dia, &conpoint->pos,
83 CONNECTIONPOINT_SIZE, CONNECTIONPOINT_SIZE);
84 }
85
86 /* run diagram_update_connections_object on all selected objects. */
87 void
diagram_update_connections_selection(Diagram * dia)88 diagram_update_connections_selection(Diagram *dia)
89 {
90 GList *list = dia->data->selected;
91
92 while (list!=NULL) {
93 DiaObject * selected_obj = (DiaObject *) list->data;
94
95 diagram_update_connections_object(dia, selected_obj, TRUE);
96
97 list = g_list_next(list);
98 }
99 }
100
101 /* Updates all objects connected to the 'obj' object.
102 Calls this function recursively for objects modified.
103
104 If update_nonmoved is TRUE, also objects that have not
105 moved since last time is updated. This is not propagated
106 in the recursion.
107 */
108 void
diagram_update_connections_object(Diagram * dia,DiaObject * obj,int update_nonmoved)109 diagram_update_connections_object(Diagram *dia, DiaObject *obj,
110 int update_nonmoved)
111 {
112 int i,j;
113 ConnectionPoint *cp;
114 GList *list;
115 DiaObject *connected_obj;
116 Handle *handle;
117
118 for (i=0;i<obj->num_connections;i++) {
119 cp = obj->connections[i];
120 if ((update_nonmoved) ||
121 (distance_point_point_manhattan(&cp->pos, &cp->last_pos) > CHANGED_TRESHOLD)) {
122 cp->last_pos = cp->pos;
123
124 list = cp->connected;
125 while (list!=NULL) {
126 connected_obj = (DiaObject *) list->data;
127
128 object_add_updates(connected_obj, dia);
129 handle = NULL;
130 for (j=0;j<connected_obj->num_handles;j++) {
131 if (connected_obj->handles[j]->connected_to == cp) {
132 handle = connected_obj->handles[j];
133 connected_obj->ops->move_handle(connected_obj, handle, &cp->pos,
134 cp, HANDLE_MOVE_CONNECTED,0);
135 }
136 }
137 object_add_updates(connected_obj, dia);
138
139 diagram_update_connections_object(dia, connected_obj, FALSE);
140
141 list = g_list_next(list);
142 }
143 }
144 }
145 if (obj->children) {
146 GList *child;
147 for (child = obj->children; child != NULL; child = child->next) {
148 DiaObject *child_obj = (DiaObject *)child->data;
149 diagram_update_connections_object(dia, child_obj, update_nonmoved);
150 }
151 }
152 }
153
154 void
ddisplay_connect_selected(DDisplay * ddisp)155 ddisplay_connect_selected(DDisplay *ddisp)
156 {
157 GList *list;
158 DiaObject *selected_obj;
159 int i;
160
161 list = ddisp->diagram->data->selected;
162
163 while (list!=NULL) {
164 selected_obj = (DiaObject *) list->data;
165
166 for (i=0; i<selected_obj->num_handles; i++) {
167 if (selected_obj->handles[i]->connect_type != HANDLE_NONCONNECTABLE) {
168 object_connect_display(ddisp, selected_obj, selected_obj->handles[i], FALSE);
169 }
170 }
171
172 list = g_list_next(list);
173 }
174 }
175
176 void
diagram_unconnect_selected(Diagram * dia)177 diagram_unconnect_selected(Diagram *dia)
178 {
179 GList *list;
180 DiaObject *selected_obj;
181 Handle *handle;
182 int i;
183
184 list = dia->data->selected;
185
186 while (list!=NULL) {
187 selected_obj = (DiaObject *) list->data;
188
189 for (i=0; i<selected_obj->num_handles; i++) {
190 handle = selected_obj->handles[i];
191
192 if ((handle->connected_to != NULL) &&
193 (handle->connect_type == HANDLE_CONNECTABLE)){
194 /* don't do this if type is HANDLE_CONNECTABLE_BREAK */
195 if (!diagram_is_selected(dia, handle->connected_to->object)) {
196 Change *change = undo_unconnect(dia, selected_obj, handle);
197 (change->apply)(change, dia);
198 }
199 }
200 }
201
202 list = g_list_next(list);
203 }
204 }
205
206
207