gui/graph_displayer_canvas.cc
author hegyi
Fri, 17 Jun 2005 12:25:53 +0000
changeset 1501 39d59aee2a1a
parent 1500 a222eb109e52
child 1505 7121597da9ba
permissions -rwxr-xr-x
Very small bug is corrected: if node creator tool is active, the small red arrows won't move, if you click on them and if you drag the newly created node... 'was hard to notice it :-)
     1 #include <graph_displayer_canvas.h>
     2 #include <broken_edge.h>
     3 #include <math.h>
     4 
     5 GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm, MapStorage & ms):g(gr),nodesmap(g),edgesmap(g),edgetextmap(g),displayed_graph(*(root()), 0, 0),mapstorage(ms),isbutton(0),active_item(NULL),target_item(NULL)
     6 {
     7   
     8   actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
     9   actual_tool=CREATE_NODE;
    10 
    11   active_node=INVALID;
    12   active_edge=INVALID;
    13 
    14   //set_center_scroll_region(true);
    15 
    16   //first edges are drawn, to hide joining with nodes later
    17 
    18   for (EdgeIt i(g); i!=INVALID; ++i)
    19   {
    20 
    21     //drawing green lines, coordinates are from cm
    22 
    23     Gnome::Canvas::Points coos;
    24     coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
    25     coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
    26     
    27     edgesmap[i]=new BrokenEdge(displayed_graph, coos, *this);
    28     *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
    29     edgesmap[i]->property_width_pixels().set_value(10);    
    30     
    31     //initializing edge-text as well, to empty string
    32 
    33     double x1, x2, y1, y2;
    34     edgesmap[i]->get_bounds(x1, y1, x2, y2);
    35     
    36     edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
    37     edgetextmap[i]->property_fill_color().set_value("black");
    38   }
    39 
    40   //afterwards nodes come to be drawn
    41 
    42   NodeIt i(g);
    43   int maxx=0, maxy=0, minx=(int)cm[i].x, miny=(int)cm[i].y;
    44 
    45   for (; i!=INVALID; ++i)
    46   {
    47     //minimum and maximum is gathered to be able to zoom to the graph correctly (whole figure should be seen)
    48 
    49     if(cm[i].x>maxx)maxx=(int)cm[i].x;
    50     if(cm[i].y>maxy)maxy=(int)cm[i].y;
    51     if(cm[i].x<minx)minx=(int)cm[i].x;
    52     if(cm[i].y<miny)miny=(int)cm[i].y;
    53 
    54     //drawing bule nodes, with black line around them
    55 
    56     nodesmap[i]=new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
    57     *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
    58     *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
    59     //!!!!!!! (nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
    60   }
    61 
    62   updateScrollRegion();
    63 }
    64 
    65 GraphDisplayerCanvas::~GraphDisplayerCanvas()
    66 {
    67 
    68   //writing out the end state of the graph
    69   //\todo all the maps has to be write out!
    70 
    71   Graph::NodeMap <int> id(g);
    72   Graph::NodeMap <double> xc(g);
    73   Graph::NodeMap <double> yc(g);
    74   
    75   int j=1;
    76   
    77   for (NodeIt i(g); i!=INVALID; ++i)
    78   {
    79     double x1,y1,x2,y2;
    80     nodesmap[i]->get_bounds(x1, y1, x2, y2);
    81     
    82     id[i]=j++;
    83     xc[i]=(x1+x2)/2;
    84     yc[i]=(y1+y2)/2;
    85   }
    86 
    87   GraphWriter<Graph> writer(std::cout,g);
    88   
    89   writer.writeNodeMap("id", id);
    90   writer.writeNodeMap("coordinates_x", xc);
    91   writer.writeNodeMap("coordinates_y", yc);
    92   writer.run();
    93 }
    94 
    95 int GraphDisplayerCanvas::changeLineWidth (std::string mapname)
    96 {
    97   for (EdgeIt i(g); i!=INVALID; ++i)
    98   {
    99     int w=(int)(*(mapstorage.edgemap_storage)[mapname])[i];
   100     edgesmap[i]->property_width_pixels().set_value(w);
   101   }
   102   return 0;
   103 };
   104 
   105 int GraphDisplayerCanvas::changeColor (std::string mapname)
   106 {  
   107 
   108   //function maps the range of the maximum and
   109   //the minimum of the nodemap to the range of
   110   //green in RGB
   111 
   112   for (EdgeIt i(g); i!=INVALID; ++i)
   113   {
   114     double w=(*(mapstorage.edgemap_storage)[mapname])[i];
   115     double max=mapstorage.maxOfEdgeMap(mapname);
   116     double min=mapstorage.minOfEdgeMap(mapname);
   117       
   118     //std::cout<<w<<" "<<max<<" "<<min<<" "<<100*(w-min)/(max-min)<<std::endl;
   119     Gdk::Color color;
   120     if(max!=min)
   121     {
   122       color.set_rgb_p (0, 100*(w-min)/(max-min), 0);
   123     }
   124     else
   125     {
   126       color.set_rgb_p (0, 100, 0);
   127     }
   128 
   129     edgesmap[i]->property_fill_color_gdk().set_value(color);
   130   }
   131   return 0;
   132 };
   133 
   134 int GraphDisplayerCanvas::changeText (std::string mapname)
   135 {
   136 
   137   //the number in the map will be written on the edge
   138   //EXCEPT when the name of the map is Text, because
   139   //in that case empty string will be written, because
   140   //that is the deleter map
   141   //\todo isn't it a bit woodcutter?
   142 
   143   for (EdgeIt i(g); i!=INVALID; ++i)
   144   {
   145     if(mapname!="Text")
   146     {
   147       double number=(*(mapstorage.edgemap_storage)[mapname])[i];
   148       int length=(int)(floor(log(number)/log(10)))+1;
   149       int maxpos=(int)(pow(10,length-1));
   150       int strl=length+1+RANGE;
   151       char * str=new char[strl];
   152       str[length]='.';
   153       str[strl]='\0';
   154       
   155       for(int j=0;j<strl;j++)
   156       {
   157 	if(j!=length)
   158         {
   159 	  int digit=(int)(number/maxpos);
   160 	  str[j]=(digit+'0');
   161 	  number-=digit*maxpos;
   162 	  number*=10;
   163         }
   164       }
   165       
   166       edgetextmap[i]->property_text().set_value(str);
   167     }
   168     else
   169     {
   170       edgetextmap[i]->property_text().set_value("");
   171     }
   172   }
   173   return 0;
   174 };
   175 
   176 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
   177 {
   178   switch(e->type)
   179   {
   180     case GDK_BUTTON_PRESS:
   181       //we mark the location of the event to be able to calculate parameters of dragging
   182       clicked_x=e->button.x;
   183       clicked_y=e->button.y;
   184       active_item=(get_item_at(e->button.x, e->button.y));
   185       isbutton=1;
   186       break;
   187     case GDK_BUTTON_RELEASE:
   188       isbutton=0;
   189       active_item=NULL;
   190       updateScrollRegion();
   191       break;
   192     case GDK_MOTION_NOTIFY:
   193       //we only have to do sg. if the mouse button is pressed
   194       if(isbutton)
   195       {
   196 	//new coordinates will be the old values,
   197 	//because the item will be moved to the
   198 	//new coordinate therefore the new movement
   199 	//has to be calculated from here
   200 
   201         double dx=e->motion.x-clicked_x;
   202         double dy=e->motion.y-clicked_y;
   203         active_item->move(dx, dy);
   204         clicked_x=e->motion.x;
   205         clicked_y=e->motion.y;
   206 
   207 	//all the edges connected to the moved point has to be redrawn
   208 
   209         EdgeIt e;
   210         g.firstOut(e,n);
   211         for(;e!=INVALID;g.nextOut(e))
   212         {
   213             Gnome::Canvas::Points coos;
   214             double x1, x2, y1, y2;
   215 
   216             nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
   217             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   218 
   219             nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
   220             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   221 
   222             edgesmap[e]->property_points().set_value(coos);
   223 
   224 	    edgesmap[e]->get_bounds(x1, y1, x2, y2);
   225 
   226 	    edgetextmap[e]->property_x().set_value((x1+x2)/2);
   227 	    edgetextmap[e]->property_y().set_value((y1+y2)/2);
   228         }
   229 
   230         g.firstIn(e,n);
   231         for(;e!=INVALID;g.nextIn(e))
   232         {
   233             Gnome::Canvas::Points coos;
   234             double x1, x2, y1, y2;
   235 
   236             nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
   237             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   238 
   239             nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
   240             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   241 
   242             edgesmap[e]->property_points().set_value(coos);
   243 
   244 	    edgesmap[e]->get_bounds(x1, y1, x2, y2);
   245 
   246 	    edgetextmap[e]->property_x().set_value((x1+x2)/2);
   247 	    edgetextmap[e]->property_y().set_value((y1+y2)/2);
   248         }
   249       }
   250     default: break;
   251   }
   252   return true;
   253 }
   254 
   255 bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
   256 {
   257   Gnome::Canvas::CanvasAA::on_expose_event(event);
   258   //usleep(10000);
   259   //rezoom();
   260   return true;
   261 }
   262 
   263 void GraphDisplayerCanvas::zoomIn()
   264 {
   265   set_pixels_per_unit(
   266       (1.0 + (double) zoom_step / 100.0) * get_pixels_per_unit());
   267 }
   268 
   269 void GraphDisplayerCanvas::zoomOut()
   270 {
   271   set_pixels_per_unit(
   272       (1.0 - (double) zoom_step / 100.0) * get_pixels_per_unit());
   273 }
   274 
   275 void GraphDisplayerCanvas::zoomFit()
   276 {
   277   // get the height and width of the canvas
   278   Gtk::Allocation a = get_allocation();
   279   int aw = a.get_width();
   280   int ah = a.get_height();
   281   // add some space
   282   aw -= 5; if (aw < 0) aw = 0;
   283   ah -= 5; if (ah < 0) ah = 0;
   284 
   285   // get the bounding box of the graph
   286   double wx1, wy1, wx2, wy2;
   287   Gnome::Canvas::Item* pCanvasItem = root();
   288   pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
   289 
   290   // fit the graph to the window
   291   double ppu1 = (double) aw / fabs(wx2 - wx1);
   292   double ppu2 = (double) ah / fabs(wy2 - wy1);
   293   set_pixels_per_unit((ppu1 < ppu2) ? ppu1 : ppu2);
   294 }
   295 
   296 void GraphDisplayerCanvas::zoom100()
   297 {
   298   set_pixels_per_unit(1.0);
   299 }
   300 
   301 void GraphDisplayerCanvas::updateScrollRegion()
   302 {
   303   double wx1, wy1, wx2, wy2;
   304   Gnome::Canvas::Item* pCanvasItem = root();
   305   pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
   306   set_scroll_region(wx1, wy1, wx2, wy2);
   307 }
   308 
   309 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
   310 {
   311   actual_handler.disconnect();
   312 
   313   if(actual_tool==CREATE_EDGE)
   314     {
   315 	GdkEvent * generated=new GdkEvent();
   316 	generated->type=GDK_BUTTON_RELEASE;
   317 	generated->button.button=3;
   318 	create_edge_event_handler(generated);      
   319     }
   320 
   321   actual_tool=newtool;
   322 
   323   switch(newtool)
   324     {
   325     case MOVE:
   326       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
   327       break;
   328 
   329       //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
   330     case CREATE_NODE:
   331       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
   332       break;
   333 
   334     case CREATE_EDGE:
   335       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
   336       break;
   337 
   338     case ERASER:
   339       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraser_event_handler), false);
   340       break;
   341 
   342     default:
   343       break;
   344     }
   345 }
   346 
   347 int GraphDisplayerCanvas::get_actual_tool()
   348 {
   349   return actual_tool;
   350 }
   351 
   352 bool GraphDisplayerCanvas::move_event_handler(GdkEvent* e)
   353 {
   354   switch(e->type)
   355   {
   356     case GDK_BUTTON_PRESS:
   357       //we mark the location of the event to be able to calculate parameters of dragging
   358       clicked_x=e->button.x;
   359       clicked_y=e->button.y;
   360       active_item=(get_item_at(e->button.x, e->button.y));
   361       active_node=INVALID;
   362       for (NodeIt i(g); i!=INVALID; ++i)
   363 	{
   364 	  if(nodesmap[i]==active_item)
   365 	    {
   366 	      active_node=i;
   367 	    }
   368 	}
   369       switch(e->button.button)
   370 	{
   371 	case 3:      
   372 	  isbutton=3;
   373 	  break;
   374 	default:
   375 	  isbutton=1;
   376 	  break;
   377 	}
   378       break;
   379     case GDK_BUTTON_RELEASE:
   380       isbutton=0;
   381       active_item=NULL;
   382       active_node=INVALID;
   383       updateScrollRegion();
   384       break;
   385     case GDK_MOTION_NOTIFY:
   386       //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
   387       if(active_node!=INVALID)
   388       {
   389 	//new coordinates will be the old values,
   390 	//because the item will be moved to the
   391 	//new coordinate therefore the new movement
   392 	//has to be calculated from here
   393 
   394         double dx=e->motion.x-clicked_x;
   395         double dy=e->motion.y-clicked_y;
   396 
   397         active_item->move(dx, dy);
   398 
   399         clicked_x=e->motion.x;
   400         clicked_y=e->motion.y;
   401 
   402 	//all the edges connected to the moved point has to be redrawn
   403         EdgeIt ei;
   404 
   405         g.firstOut(ei,active_node);
   406 
   407         for(;ei!=INVALID;g.nextOut(ei))
   408         {
   409             Gnome::Canvas::Points coos;
   410             double x1, x2, y1, y2;
   411 
   412             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   413             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   414 
   415             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   416             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   417 
   418 	    if(isbutton==3)
   419 	      {
   420 		edgesmap[ei]->set_points(coos);
   421 	      }
   422 	    else
   423 	      {
   424 		edgesmap[ei]->set_points(coos,true);
   425 	      }
   426 
   427 	    edgesmap[ei]->get_bounds(x1, y1, x2, y2);
   428 
   429 	    edgetextmap[ei]->property_x().set_value((x1+x2)/2);
   430 	    edgetextmap[ei]->property_y().set_value((y1+y2)/2);
   431         }
   432 
   433         g.firstIn(ei,active_node);
   434         for(;ei!=INVALID;g.nextIn(ei))
   435         {
   436             Gnome::Canvas::Points coos;
   437             double x1, x2, y1, y2;
   438 
   439             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   440             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   441 
   442             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   443             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   444 
   445 	    if(isbutton==3)
   446 	      {
   447 		edgesmap[ei]->set_points(coos);
   448 	      }
   449 	    else
   450 	      {
   451 		edgesmap[ei]->set_points(coos,true);
   452 	      }
   453 
   454 	    edgesmap[ei]->get_bounds(x1, y1, x2, y2);
   455 
   456 	    edgetextmap[ei]->property_x().set_value((x1+x2)/2);
   457 	    edgetextmap[ei]->property_y().set_value((y1+y2)/2);
   458         }
   459       }
   460     default: break;
   461   }
   462 
   463   return true;
   464 }
   465 
   466 bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
   467 {
   468   switch(e->type)
   469     {
   470 
   471       //draw the new node in red at the clicked place
   472     case GDK_BUTTON_PRESS:
   473       isbutton=1;
   474 
   475       active_node=NodeIt(g,g.addNode());
   476 
   477       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   478 
   479       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   480       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   481       *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   482       *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
   483       (nodesmap[active_node])->show();
   484       break;
   485 
   486       //move the new node
   487     case GDK_MOTION_NOTIFY:
   488       {
   489 	double world_motion_x, world_motion_y;
   490 	GdkEvent * generated=new GdkEvent();
   491 	window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
   492 	generated->motion.x=world_motion_x;
   493 	generated->motion.y=world_motion_y;
   494 	generated->type=GDK_MOTION_NOTIFY;
   495 	move_event_handler(generated);      
   496 	break;
   497       }
   498 
   499       //finalize the new node
   500     case GDK_BUTTON_RELEASE:
   501       isbutton=0;
   502       *active_item << Gnome::Canvas::Properties::fill_color("blue");
   503       active_item=NULL;
   504       active_node=INVALID;
   505       updateScrollRegion();
   506       break;
   507     default:
   508       break;
   509     }
   510   return false;
   511 }
   512 
   513 bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
   514 {
   515   switch(e->type)
   516     {
   517     case GDK_BUTTON_PRESS:
   518       //in edge creatino right button has special meaning
   519       if(e->button.button!=3)
   520 	{
   521 	  //there is not yet selected node
   522 	  if(active_node==INVALID)
   523 	    {
   524 	      //we mark the location of the event to be able to calculate parameters of dragging
   525 	      clicked_x=e->button.x;
   526 	      clicked_y=e->button.y;
   527 	      active_item=(get_item_at(e->button.x, e->button.y));
   528 	      active_node=INVALID;
   529 	      for (NodeIt i(g); i!=INVALID; ++i)
   530 		{
   531 		  if(nodesmap[i]==active_item)
   532 		    {
   533 		      active_node=i;
   534 		    }
   535 		}
   536 	      //the clicked item is really a node
   537 	      if(active_node!=INVALID)
   538 		{
   539 		  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   540 		  isbutton=1;
   541 		}
   542 	      //clicked item was not a node. It could be e.g. edge.
   543 	      else
   544 		{
   545 		  active_item=NULL;
   546 		}
   547 	    }
   548 	  //we only have to do sg. if the mouse button
   549 	  // is pressed already once AND the click was
   550 	  // on a node that was found in the set of 
   551 	  //nodes, and now we only search for the second 
   552 	  //node
   553 	  else
   554 	    {
   555 	      target_item=(get_item_at(e->button.x, e->button.y));
   556 	      Graph::NodeIt target_node=INVALID;
   557 	      for (NodeIt i(g); i!=INVALID; ++i)
   558 		{
   559 		  if(nodesmap[i]==target_item)
   560 		    {
   561 		      target_node=i;
   562 		    }
   563 		}
   564 	      //the clicked item is a node, the edge can be drawn
   565 	      if(target_node!=INVALID)
   566 		{
   567 		  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   568 
   569 		  //creating new edge
   570 		  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   571 	  
   572 		  //calculating coordinates of new edge
   573 		  Gnome::Canvas::Points coos;
   574 		  double x1, x2, y1, y2;
   575 	  
   576 		  active_item->get_bounds(x1, y1, x2, y2);
   577 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   578 
   579 		  target_item->get_bounds(x1, y1, x2, y2);
   580 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   581 
   582 		  //drawing new edge
   583 		  edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
   584 		  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   585 		  edgesmap[active_edge]->property_width_pixels().set_value(10);
   586 
   587 		  //redraw nodes to blank terminations of the new edge
   588 		  target_item->raise_to_top();
   589 		  active_item->raise_to_top();
   590 
   591 		  //initializing edge-text as well, to empty string
   592 		  edgesmap[active_edge]->get_bounds(x1, y1, x2, y2);
   593 		  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
   594 		  edgetextmap[active_edge]->property_fill_color().set_value("black");
   595 		}
   596 	      //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
   597 	      else
   598 		{
   599 		  target_item=NULL;
   600 		}
   601 	    }
   602 	}
   603       break;
   604     case GDK_BUTTON_RELEASE:
   605       isbutton=0;
   606       //we clear settings in two cases
   607       //1: the edge is ready (target_item has valid value)
   608       //2: the edge creation is cancelled with right button
   609       if((target_item)||(e->button.button==3))
   610 	{
   611 	  if(active_item)
   612 	    {
   613 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   614 	      active_item=NULL;
   615 	    }
   616 	  if(target_item)
   617 	    {
   618 	      *target_item << Gnome::Canvas::Properties::fill_color("blue");
   619 	      target_item=NULL;
   620 	    }
   621 	  active_node=INVALID;
   622 	  active_edge=INVALID;
   623 	}
   624       break;
   625     default:
   626       break;
   627     }
   628   return false;
   629 }
   630 
   631 bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
   632 {
   633   switch(e->type)
   634     {
   635     case GDK_BUTTON_PRESS:
   636       active_item=(get_item_at(e->button.x, e->button.y));
   637       active_node=INVALID;
   638       active_edge=INVALID;
   639       for (NodeIt i(g); i!=INVALID; ++i)
   640 	{
   641 	  if(nodesmap[i]==active_item)
   642 	    {
   643 	      active_node=i;
   644 	    }
   645 	}
   646       if(active_node==INVALID)
   647 	{
   648 	  for (EdgeIt i(g); i!=INVALID; ++i)
   649 	    {
   650 	      if(edgesmap[i]==active_item)
   651 		{
   652 		  active_edge=i;
   653 		}
   654 	    }
   655 	}
   656     *active_item << Gnome::Canvas::Properties::fill_color("red");
   657       break;
   658 
   659     case GDK_BUTTON_RELEASE:
   660       if(active_item==(get_item_at(e->button.x, e->button.y)))
   661 	{
   662 	  if(active_node!=INVALID)
   663 	    {
   664 
   665 	      //collecting edges to delete
   666 	      EdgeIt e;
   667 	      std::set<Graph::Edge> edges_to_delete;
   668 
   669 	      g.firstOut(e,active_node);
   670 	      for(;e!=INVALID;g.nextOut(e))
   671 		{
   672 		      edges_to_delete.insert(e);
   673 		}
   674 
   675 	      g.firstIn(e,active_node);
   676 	      for(;e!=INVALID;g.nextIn(e))
   677 		{
   678 		      edges_to_delete.insert(e);
   679 		}
   680 
   681 	      //deleting collected edges
   682 	      for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
   683 		{
   684 		  delete_item(*edge_set_it);
   685 		}
   686 	      delete_item(active_node);
   687 	    }
   688 	  //a simple edge was chosen
   689 	  else
   690 	    {
   691 	      delete_item(active_edge);
   692 	    }
   693 
   694 	  
   695 	}
   696       //pointer was moved, deletion is cancelled
   697       else
   698 	{
   699 	  if(active_node!=INVALID)
   700 	    {
   701 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   702 	    }
   703 	  else
   704 	    {
   705 	      *active_item << Gnome::Canvas::Properties::fill_color("green");
   706 	    }
   707 	}
   708       //reseting datas
   709       active_item=NULL;
   710       active_edge=INVALID;
   711       active_node=INVALID;
   712       break;
   713 
   714     case GDK_MOTION_NOTIFY:
   715       break;
   716 
   717     default:
   718       break;
   719     }
   720   return true;
   721 }
   722 
   723 void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
   724 {
   725   delete(nodesmap[node_to_delete]);
   726   g.erase(node_to_delete);
   727 }
   728 
   729 void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
   730 {
   731   delete(edgesmap[edge_to_delete]);
   732   g.erase(edge_to_delete);
   733 }
   734 
   735 void GraphDisplayerCanvas::delete_item(Graph::Edge edge_to_delete)
   736 {
   737   delete(edgesmap[edge_to_delete]);
   738   g.erase(edge_to_delete);
   739 }
   740