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