1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #include "selectionfuncs.h"
15 #include "topviewfuncs.h"
16 #include "smyrna_utils.h"
17 
select_node(Agraph_t * g,Agnode_t * obj,int reverse)18 static void select_node(Agraph_t* g,Agnode_t*  obj,int reverse)
19 {
20     Agsym_t* sel_attr = GN_selected(g);
21 
22     if(!sel_attr)
23 	sel_attr = GN_selected(g) = agattr(g, AGNODE,"selected","0");
24     if(!reverse)
25     {
26         agxset(obj,sel_attr,"1");
27 	ND_selected(obj) = 1;
28     }
29     else
30     {
31 	if(ND_selected(obj)==1)
32 	{
33             agxset(obj,sel_attr,"0");
34 	    ND_selected(obj) = 0;
35 	    ND_printLabel(obj) = 0;
36 	}
37 	else
38 	{
39             agxset(obj,sel_attr,"1");
40 	    ND_selected(obj) = 1;
41 	}
42 
43     }
44 
45 
46 }
select_edge(Agraph_t * g,Agedge_t * obj,int reverse)47 static void select_edge(Agraph_t* g,Agedge_t*  obj,int reverse)
48 {
49     Agsym_t* sel_attr = GE_selected(g);
50 
51     if (!sel_attr)
52 	sel_attr = GE_selected(g) = agattr(g, AGEDGE,"selected","0");
53     if (!reverse)
54     {
55 	agxset(obj,sel_attr,"1");
56 	ED_selected(obj) = 1;
57     }
58     else
59     {
60 	if (ED_selected(obj) == 1)
61 	{
62 	    agxset(obj,sel_attr,"0");
63 	    ED_selected(obj) = 0;
64 	    ED_printLabel(obj) = 0;
65 	}
66 	else
67 	{
68 	    agxset(obj,sel_attr,"1");
69 	    ED_selected(obj) = 1;
70 	}
71     }
72 
73 
74 }
75 
76 
pick_objects_in_rect(Agraph_t * g,GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)77 static void pick_objects_in_rect(Agraph_t* g,GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)
78 {
79     Agnode_t *v;
80     Agedge_t *e;
81     glCompPoint posT;
82     glCompPoint posH;
83     glCompPoint posN;
84 
85     for (v = agfstnode(g); v; v = agnxtnode(g, v))
86     {
87 	if(view->Topview->sel.selectNodes==1)
88 	{
89 	    posN = ND_A(v);
90 	    if(!ND_visible(v))
91 		continue;
92 	    if(is_point_in_rectangle(posN.x,posN.y,x1,y1,x2-x1,y2-y1) )
93 		select_node(g,v,0);
94 	}
95 	if(view->Topview->sel.selectEdges==1) {
96 	    for (e = agfstout(g, v); e; e = agnxtout(g, e))
97 	    {
98 		posT = ED_posTail(e);
99 		posH = ED_posHead(e);
100     		if(is_point_in_rectangle(posT.x,posT.y,x1,y1,x2-x1,y2-y1))
101 		    if(is_point_in_rectangle(posH.x,posH.y,x1,y1,x2-x1,y2-y1))
102 			select_edge(g,e,0);
103 	    }
104 	}
105     }
106 }
107 
108 
109 
pick_object(Agraph_t * g,glCompPoint p)110 static void* pick_object(Agraph_t* g,glCompPoint p)
111 {
112     Agnode_t *v;
113     Agedge_t *e;
114     glCompPoint posT;
115     glCompPoint posH;
116     glCompPoint posN;
117     int defaultNodeShape;
118     float dist=999999999;
119     GLfloat nd; /*node distance to point*/
120     GLfloat ed; /*edge distance to point*/
121     GLfloat nodeSize=0;
122     void* rv=(void*)0;
123 
124     defaultNodeShape=getAttrBool(g,g,"defaultnodeshape",0);
125 
126     if(defaultNodeShape==0)
127         nodeSize=GetOGLDistance(view->nodeScale*view->Topview->fitin_zoom/view->zoom);
128 
129     for (v = agfstnode(g); v; v = agnxtnode(g, v))
130     {
131 	if(!ND_visible(v))
132 	    continue;
133 	posN = ND_A(v);
134 	if(defaultNodeShape==1)
135 	{
136 	    nodeSize = ND_size(v);
137 	}
138 
139 	nd=distBetweenPts(posN,p,nodeSize);
140 	if( nd < dist )
141 	{
142 	    rv=v;dist=nd;
143 	}
144 
145 	for (e = agfstout(g, v); e; e = agnxtout(g, e))
146 	{
147 	    posT = ED_posTail(e);
148 	    posH = ED_posHead(e);
149 	    ed=point_to_lineseg_dist(p, posT,posH);
150 	    if( ed < dist ) {rv=e;dist=ed;}
151 	}
152     }
153     return rv;
154 }
155 
pick_object_xyz(Agraph_t * g,topview * t,GLfloat x,GLfloat y,GLfloat z)156 void pick_object_xyz(Agraph_t* g,topview* t,GLfloat x,GLfloat y,GLfloat z)
157 {
158     glCompPoint p;
159     void* a;
160     p.x=x;p.y=y;p.z=z;
161     a=pick_object(g,p);
162     if (!a)
163 	return;
164     if(agobjkind(a)==AGNODE)
165     {
166 	select_node(g,a,1);
167 	ND_printLabel((Agnode_t*)a) = 1;
168 
169 	cacheSelectedNodes(g,t);
170 
171     }
172     if(agobjkind(a)==AGEDGE)
173     {
174 	select_edge(g,a,1);
175 	cacheSelectedEdges(g,t);
176 	ED_printLabel((Agedge_t*)a) = 1;
177     }
178 }
pick_objects_rect(Agraph_t * g)179 void pick_objects_rect(Agraph_t* g)
180 {
181 
182     GLfloat x1;
183     GLfloat y1;
184     GLfloat x2;
185     GLfloat y2;
186     if(view->mouse.GLfinalPos.x > view->mouse.GLinitPos.x)
187     {
188         x1=view->mouse.GLinitPos.x;
189 	x2=view->mouse.GLfinalPos.x;
190     }
191     else
192     {
193         x2=view->mouse.GLinitPos.x;
194 	x1=view->mouse.GLfinalPos.x;
195 
196     }
197     if(view->mouse.GLfinalPos.y > view->mouse.GLinitPos.y)
198     {
199         y1=view->mouse.GLinitPos.y;
200 	y2=view->mouse.GLfinalPos.y;
201     }
202     else
203     {
204         y2=view->mouse.GLinitPos.y;
205 	y1=view->mouse.GLfinalPos.y;
206     }
207     pick_objects_in_rect(g,x1,y1,x2,y2);
208     cacheSelectedNodes(g,view->Topview);
209     cacheSelectedEdges(g,view->Topview);
210 }
211 
212 
213 
deselect_all(Agraph_t * g)214 void deselect_all(Agraph_t* g)
215 {
216     Agnode_t *v;
217     Agedge_t *e;
218     Agsym_t* nsel_attr = GN_selected(g);
219     Agsym_t* esel_attr = GE_selected(g);
220     if(!nsel_attr)
221 	nsel_attr = GN_selected(g) = agattr(g, AGNODE,"selected","0");
222     if(!esel_attr)
223 	esel_attr = GE_selected(g) = agattr(g, AGEDGE,"selected","0");
224     for (v = agfstnode(g); v; v = agnxtnode(g, v))
225     {
226 	agxset(v,nsel_attr,"0");
227 	ND_selected(v) = 0;
228 	ND_printLabel(v) = 0;
229 
230 	for (e = agfstout(g, v); e; e = agnxtout(g, e))
231 	{
232 	    agxset(e,esel_attr,"0");
233 	    ED_selected(e) = 0;
234 	    ED_printLabel(e) = 0;
235 	}
236     }
237     cacheSelectedNodes(g,view->Topview);
238     cacheSelectedEdges(g,view->Topview);
239 }
240 
clear_selpoly(glCompPoly * sp)241 void clear_selpoly(glCompPoly* sp)
242 {
243     sp->pts=realloc(sp->pts,0);
244     sp->cnt=0;
245 }
close_poly(glCompPoly * selPoly,glCompPoint pt)246 static int close_poly(glCompPoly* selPoly,glCompPoint pt)
247 {
248     /* int i=0; */
249     float EPS=GetOGLDistance(3);
250     if (selPoly->cnt < 2)
251 	return 0;
252     if(
253 	( (selPoly->pts[0].x-pt.x) < EPS) &&
254 	( (selPoly->pts[0].y-pt.y) < EPS))
255 	return 1;
256     return 0;
257 }
258 
259 
select_polygon(Agraph_t * g,glCompPoly * selPoly)260 static void select_polygon (Agraph_t* g,glCompPoly* selPoly)
261 {
262     Agnode_t *v;
263     glCompPoint posN;
264 
265     for (v = agfstnode(g); v; v = agnxtnode(g, v))
266     {
267 	posN = ND_A(v);
268 	if(point_in_polygon(selPoly,posN))
269 	    select_node(g,v,0);
270     }
271     cacheSelectedNodes(g,view->Topview);
272 }
273 
274 
add_selpoly(Agraph_t * g,glCompPoly * selPoly,glCompPoint pt)275 void add_selpoly(Agraph_t* g,glCompPoly* selPoly,glCompPoint pt)
276 {
277     if(!close_poly(selPoly,pt))
278     {
279 	selPoly->cnt ++;
280 	selPoly->pts=realloc(selPoly->pts,sizeof(glCompPoint)*selPoly->cnt);
281 	selPoly->pts[selPoly->cnt-1].x=pt.x;
282 	selPoly->pts[selPoly->cnt-1].y=pt.y;
283 	selPoly->pts[selPoly->cnt-1].z=0;
284     }
285     else
286     {
287 	select_polygon (g,selPoly);
288 	clear_selpoly(selPoly);
289     }
290 }
291 
292