COIN-OR::LEMON - Graph Library

source: lemon-0.x/gui/graph_displayer_canvas-event.cc @ 1510:cde847387b5a

Last change on this file since 1510:cde847387b5a was 1510:cde847387b5a, checked in by Hegyi Péter, 15 years ago

File graph_displayer is split in functional parts.

  • Property exe set to *
File size: 12.1 KB
Line 
1#include <graph_displayer_canvas.h>
2#include <broken_edge.h>
3#include <math.h>
4
5
6bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
7{
8  Gnome::Canvas::CanvasAA::on_expose_event(event);
9  //usleep(10000);
10  //rezoom();
11  return true;
12}
13
14void GraphDisplayerCanvas::changeEditorialTool(int newtool)
15{
16  actual_handler.disconnect();
17
18  if(actual_tool==CREATE_EDGE)
19    {
20        GdkEvent * generated=new GdkEvent();
21        generated->type=GDK_BUTTON_RELEASE;
22        generated->button.button=3;
23        create_edge_event_handler(generated);     
24    }
25
26  actual_tool=newtool;
27
28  switch(newtool)
29    {
30    case MOVE:
31      actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
32      break;
33
34      //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
35    case CREATE_NODE:
36      actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
37      break;
38
39    case CREATE_EDGE:
40      actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
41      break;
42
43    case ERASER:
44      actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraser_event_handler), false);
45      break;
46
47    default:
48      break;
49    }
50}
51
52int GraphDisplayerCanvas::get_actual_tool()
53{
54  return actual_tool;
55}
56
57bool GraphDisplayerCanvas::move_event_handler(GdkEvent* e)
58{
59  switch(e->type)
60  {
61    case GDK_BUTTON_PRESS:
62      //we mark the location of the event to be able to calculate parameters of dragging
63      clicked_x=e->button.x;
64      clicked_y=e->button.y;
65      active_item=(get_item_at(e->button.x, e->button.y));
66      active_node=INVALID;
67      for (NodeIt i(g); i!=INVALID; ++i)
68        {
69          if(nodesmap[i]==active_item)
70            {
71              active_node=i;
72            }
73        }
74      switch(e->button.button)
75        {
76        case 3:     
77          isbutton=3;
78          break;
79        default:
80          isbutton=1;
81          break;
82        }
83      break;
84    case GDK_BUTTON_RELEASE:
85      isbutton=0;
86      active_item=NULL;
87      active_node=INVALID;
88      updateScrollRegion();
89      break;
90    case GDK_MOTION_NOTIFY:
91      //we only have to do sg. if the mouse button is pressed AND the click was on a node that was found in the set of nodes
92      if(active_node!=INVALID)
93      {
94        //new coordinates will be the old values,
95        //because the item will be moved to the
96        //new coordinate therefore the new movement
97        //has to be calculated from here
98
99        double dx=e->motion.x-clicked_x;
100        double dy=e->motion.y-clicked_y;
101
102        active_item->move(dx, dy);
103
104        clicked_x=e->motion.x;
105        clicked_y=e->motion.y;
106
107        //all the edges connected to the moved point has to be redrawn
108        EdgeIt ei;
109
110        g.firstOut(ei,active_node);
111
112        for(;ei!=INVALID;g.nextOut(ei))
113        {
114            Gnome::Canvas::Points coos;
115            double x1, x2, y1, y2;
116
117            nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
118            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
119
120            nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
121            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
122
123            if(isbutton==3)
124              {
125                edgesmap[ei]->set_points(coos);
126              }
127            else
128              {
129                edgesmap[ei]->set_points(coos,true);
130              }
131
132            xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
133            text_pos+=(xy<double>(10,10));
134            edgetextmap[ei]->property_x().set_value(text_pos.x);
135            edgetextmap[ei]->property_y().set_value(text_pos.y);
136        }
137
138        g.firstIn(ei,active_node);
139        for(;ei!=INVALID;g.nextIn(ei))
140        {
141            Gnome::Canvas::Points coos;
142            double x1, x2, y1, y2;
143
144            nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
145            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
146
147            nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
148            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
149
150            if(isbutton==3)
151              {
152                edgesmap[ei]->set_points(coos);
153              }
154            else
155              {
156                edgesmap[ei]->set_points(coos,true);
157              }
158
159            xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
160            text_pos+=(xy<double>(10,10));
161            edgetextmap[ei]->property_x().set_value(text_pos.x);
162            edgetextmap[ei]->property_y().set_value(text_pos.y);
163        }
164      }
165    default: break;
166  }
167
168  return true;
169}
170
171bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
172{
173  switch(e->type)
174    {
175
176      //draw the new node in red at the clicked place
177    case GDK_BUTTON_PRESS:
178      isbutton=1;
179
180      active_node=NodeIt(g,g.addNode());
181
182      //initiating values corresponding to new node in maps
183     
184
185      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
186
187      nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
188      active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
189      *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
190      *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
191      (nodesmap[active_node])->show();
192      break;
193
194      //move the new node
195    case GDK_MOTION_NOTIFY:
196      {
197        double world_motion_x, world_motion_y;
198        GdkEvent * generated=new GdkEvent();
199        window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
200        generated->motion.x=world_motion_x;
201        generated->motion.y=world_motion_y;
202        generated->type=GDK_MOTION_NOTIFY;
203        move_event_handler(generated);     
204        break;
205      }
206
207      //finalize the new node
208    case GDK_BUTTON_RELEASE:
209      isbutton=0;
210      *active_item << Gnome::Canvas::Properties::fill_color("blue");
211      active_item=NULL;
212      active_node=INVALID;
213      updateScrollRegion();
214      break;
215    default:
216      break;
217    }
218  return false;
219}
220
221bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
222{
223  switch(e->type)
224    {
225    case GDK_BUTTON_PRESS:
226      //in edge creation right button has special meaning
227      if(e->button.button!=3)
228        {
229          //there is not yet selected node
230          if(active_node==INVALID)
231            {
232              //we mark the location of the event to be able to calculate parameters of dragging
233              clicked_x=e->button.x;
234              clicked_y=e->button.y;
235              active_item=(get_item_at(e->button.x, e->button.y));
236              active_node=INVALID;
237              for (NodeIt i(g); i!=INVALID; ++i)
238                {
239                  if(nodesmap[i]==active_item)
240                    {
241                      active_node=i;
242                    }
243                }
244              //the clicked item is really a node
245              if(active_node!=INVALID)
246                {
247                  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
248                  isbutton=1;
249                }
250              //clicked item was not a node. It could be e.g. edge.
251              else
252                {
253                  active_item=NULL;
254                }
255            }
256          //we only have to do sg. if the mouse button
257          // is pressed already once AND the click was
258          // on a node that was found in the set of
259          //nodes, and now we only search for the second
260          //node
261          else
262            {
263              target_item=(get_item_at(e->button.x, e->button.y));
264              Graph::NodeIt target_node=INVALID;
265              for (NodeIt i(g); i!=INVALID; ++i)
266                {
267                  if(nodesmap[i]==target_item)
268                    {
269                      target_node=i;
270                    }
271                }
272              //the clicked item is a node, the edge can be drawn
273              if(target_node!=INVALID)
274                {
275                  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
276
277                  //creating new edge
278                  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
279
280                  //initiating values corresponding to new edge in maps
281                  mapstorage.init_maps_for_edge(active_edge);
282         
283                  //calculating coordinates of new edge
284                  Gnome::Canvas::Points coos;
285                  double x1, x2, y1, y2;
286         
287                  active_item->get_bounds(x1, y1, x2, y2);
288                  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
289
290                  target_item->get_bounds(x1, y1, x2, y2);
291                  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
292
293                  //drawing new edge
294                  edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
295                  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
296                  edgesmap[active_edge]->property_width_pixels().set_value(10);
297
298                  //redraw nodes to blank terminations of the new edge
299                  target_item->raise_to_top();
300                  active_item->raise_to_top();
301
302                  //initializing edge-text as well, to empty string
303                  xy<double> text_pos=edgesmap[active_edge]->get_arrow_pos();
304                  text_pos+=(xy<double>(10,10));
305
306                  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
307                  edgetextmap[active_edge]->property_fill_color().set_value("black");
308                }
309              //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
310              else
311                {
312                  target_item=NULL;
313                }
314            }
315        }
316      break;
317    case GDK_BUTTON_RELEASE:
318      isbutton=0;
319      //we clear settings in two cases
320      //1: the edge is ready (target_item has valid value)
321      //2: the edge creation is cancelled with right button
322      if((target_item)||(e->button.button==3))
323        {
324          if(active_item)
325            {
326              *active_item << Gnome::Canvas::Properties::fill_color("blue");
327              active_item=NULL;
328            }
329          if(target_item)
330            {
331              *target_item << Gnome::Canvas::Properties::fill_color("blue");
332              target_item=NULL;
333            }
334          active_node=INVALID;
335          active_edge=INVALID;
336        }
337      break;
338    default:
339      break;
340    }
341  return false;
342}
343
344bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
345{
346  switch(e->type)
347    {
348    case GDK_BUTTON_PRESS:
349      active_item=(get_item_at(e->button.x, e->button.y));
350      active_node=INVALID;
351      active_edge=INVALID;
352      for (NodeIt i(g); i!=INVALID; ++i)
353        {
354          if(nodesmap[i]==active_item)
355            {
356              active_node=i;
357            }
358        }
359      if(active_node==INVALID)
360        {
361          for (EdgeIt i(g); i!=INVALID; ++i)
362            {
363              if(edgesmap[i]==active_item)
364                {
365                  active_edge=i;
366                }
367            }
368        }
369    *active_item << Gnome::Canvas::Properties::fill_color("red");
370      break;
371
372    case GDK_BUTTON_RELEASE:
373      if(active_item==(get_item_at(e->button.x, e->button.y)))
374        {
375          if(active_node!=INVALID)
376            {
377
378              //collecting edges to delete
379              EdgeIt e;
380              std::set<Graph::Edge> edges_to_delete;
381
382              g.firstOut(e,active_node);
383              for(;e!=INVALID;g.nextOut(e))
384                {
385                      edges_to_delete.insert(e);
386                }
387
388              g.firstIn(e,active_node);
389              for(;e!=INVALID;g.nextIn(e))
390                {
391                      edges_to_delete.insert(e);
392                }
393
394              //deleting collected edges
395              for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
396                {
397                  delete_item(*edge_set_it);
398                }
399              delete_item(active_node);
400            }
401          //a simple edge was chosen
402          else
403            {
404              delete_item(active_edge);
405            }
406
407         
408        }
409      //pointer was moved, deletion is cancelled
410      else
411        {
412          if(active_node!=INVALID)
413            {
414              *active_item << Gnome::Canvas::Properties::fill_color("blue");
415            }
416          else
417            {
418              *active_item << Gnome::Canvas::Properties::fill_color("green");
419            }
420        }
421      //reseting datas
422      active_item=NULL;
423      active_edge=INVALID;
424      active_node=INVALID;
425      break;
426
427    case GDK_MOTION_NOTIFY:
428      break;
429
430    default:
431      break;
432    }
433  return true;
434}
435
436void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
437{
438  delete(nodesmap[node_to_delete]);
439  g.erase(node_to_delete);
440}
441
442void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
443{
444  delete(edgesmap[edge_to_delete]);
445  g.erase(edge_to_delete);
446}
447
448void GraphDisplayerCanvas::delete_item(Graph::Edge edge_to_delete)
449{
450  delete(edgesmap[edge_to_delete]);
451  g.erase(edge_to_delete);
452}
453
454void GraphDisplayerCanvas::text_reposition(xy<double> new_place)
455{
456  new_place+=(xy<double>(10,10));
457  edgetextmap[active_edge]->property_x().set_value(new_place.x);
458  edgetextmap[active_edge]->property_y().set_value(new_place.y);
459}
460
461void GraphDisplayerCanvas::toggle_edge_activity(BrokenEdge* active_bre, bool on)
462{
463  if(on)
464    {
465      if(active_edge!=INVALID)
466        {
467          std::cout << "ERROR!!!! Valid edge found!" << std::endl;
468        }
469      else
470        {
471          for (EdgeIt i(g); i!=INVALID; ++i)
472            {
473              if(edgesmap[i]==active_bre)
474                {
475                  active_edge=i;
476                }
477            }
478        }
479    }
480  else
481    {
482      if(active_edge!=INVALID)
483        {
484          active_edge=INVALID;
485        }
486      else
487        {
488          std::cout << "ERROR!!!! Invalid edge found!" << std::endl;
489        }
490    }
491
492}
Note: See TracBrowser for help on using the repository browser.