gui/graph_displayer_canvas.cc
author alpar
Mon, 20 Jun 2005 09:08:20 +0000
changeset 1506 e8f1ad6cc8dd
parent 1501 39d59aee2a1a
child 1509 f9113440b667
permissions -rwxr-xr-x
Some callbacks are still unimplemented
     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     xy<double> text_pos=edgesmap[i]->get_arrow_pos();
    34     text_pos+=(xy<double>(10,10));
    35 
    36     edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
    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 //Deprecated
   177 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
   178 {
   179   switch(e->type)
   180   {
   181     case GDK_BUTTON_PRESS:
   182       //we mark the location of the event to be able to calculate parameters of dragging
   183       clicked_x=e->button.x;
   184       clicked_y=e->button.y;
   185       active_item=(get_item_at(e->button.x, e->button.y));
   186       isbutton=1;
   187       break;
   188     case GDK_BUTTON_RELEASE:
   189       isbutton=0;
   190       active_item=NULL;
   191       updateScrollRegion();
   192       break;
   193     case GDK_MOTION_NOTIFY:
   194       //we only have to do sg. if the mouse button is pressed
   195       if(isbutton)
   196       {
   197 	//new coordinates will be the old values,
   198 	//because the item will be moved to the
   199 	//new coordinate therefore the new movement
   200 	//has to be calculated from here
   201 
   202         double dx=e->motion.x-clicked_x;
   203         double dy=e->motion.y-clicked_y;
   204         active_item->move(dx, dy);
   205         clicked_x=e->motion.x;
   206         clicked_y=e->motion.y;
   207 
   208 	//all the edges connected to the moved point has to be redrawn
   209 
   210         EdgeIt e;
   211         g.firstOut(e,n);
   212         for(;e!=INVALID;g.nextOut(e))
   213         {
   214             Gnome::Canvas::Points coos;
   215             double x1, x2, y1, y2;
   216 
   217             nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
   218             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   219 
   220             nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
   221             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   222 
   223             edgesmap[e]->property_points().set_value(coos);
   224 
   225 	    edgesmap[e]->get_bounds(x1, y1, x2, y2);
   226 
   227 	    edgetextmap[e]->property_x().set_value((x1+x2)/2);
   228 	    edgetextmap[e]->property_y().set_value((y1+y2)/2);
   229         }
   230 
   231         g.firstIn(e,n);
   232         for(;e!=INVALID;g.nextIn(e))
   233         {
   234             Gnome::Canvas::Points coos;
   235             double x1, x2, y1, y2;
   236 
   237             nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
   238             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   239 
   240             nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
   241             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   242 
   243             edgesmap[e]->property_points().set_value(coos);
   244 
   245 	    edgesmap[e]->get_bounds(x1, y1, x2, y2);
   246 
   247 	    edgetextmap[e]->property_x().set_value((x1+x2)/2);
   248 	    edgetextmap[e]->property_y().set_value((y1+y2)/2);
   249         }
   250       }
   251     default: break;
   252   }
   253   return true;
   254 }
   255 
   256 bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
   257 {
   258   Gnome::Canvas::CanvasAA::on_expose_event(event);
   259   //usleep(10000);
   260   //rezoom();
   261   return true;
   262 }
   263 
   264 void GraphDisplayerCanvas::zoomIn()
   265 {
   266   set_pixels_per_unit(
   267       (1.0 + (double) zoom_step / 100.0) * get_pixels_per_unit());
   268 }
   269 
   270 void GraphDisplayerCanvas::zoomOut()
   271 {
   272   set_pixels_per_unit(
   273       (1.0 - (double) zoom_step / 100.0) * get_pixels_per_unit());
   274 }
   275 
   276 void GraphDisplayerCanvas::zoomFit()
   277 {
   278   // get the height and width of the canvas
   279   Gtk::Allocation a = get_allocation();
   280   int aw = a.get_width();
   281   int ah = a.get_height();
   282   // add some space
   283   aw -= 5; if (aw < 0) aw = 0;
   284   ah -= 5; if (ah < 0) ah = 0;
   285 
   286   // get the bounding box of the graph
   287   double wx1, wy1, wx2, wy2;
   288   Gnome::Canvas::Item* pCanvasItem = root();
   289   pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
   290 
   291   // fit the graph to the window
   292   double ppu1 = (double) aw / fabs(wx2 - wx1);
   293   double ppu2 = (double) ah / fabs(wy2 - wy1);
   294   set_pixels_per_unit((ppu1 < ppu2) ? ppu1 : ppu2);
   295 }
   296 
   297 void GraphDisplayerCanvas::zoom100()
   298 {
   299   set_pixels_per_unit(1.0);
   300 }
   301 
   302 void GraphDisplayerCanvas::updateScrollRegion()
   303 {
   304   double wx1, wy1, wx2, wy2;
   305   Gnome::Canvas::Item* pCanvasItem = root();
   306   pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
   307   set_scroll_region(wx1, wy1, wx2, wy2);
   308 }
   309 
   310 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
   311 {
   312   actual_handler.disconnect();
   313 
   314   if(actual_tool==CREATE_EDGE)
   315     {
   316 	GdkEvent * generated=new GdkEvent();
   317 	generated->type=GDK_BUTTON_RELEASE;
   318 	generated->button.button=3;
   319 	create_edge_event_handler(generated);      
   320     }
   321 
   322   actual_tool=newtool;
   323 
   324   switch(newtool)
   325     {
   326     case MOVE:
   327       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
   328       break;
   329 
   330       //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
   331     case CREATE_NODE:
   332       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
   333       break;
   334 
   335     case CREATE_EDGE:
   336       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
   337       break;
   338 
   339     case ERASER:
   340       actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraser_event_handler), false);
   341       break;
   342 
   343     default:
   344       break;
   345     }
   346 }
   347 
   348 int GraphDisplayerCanvas::get_actual_tool()
   349 {
   350   return actual_tool;
   351 }
   352 
   353 bool GraphDisplayerCanvas::move_event_handler(GdkEvent* e)
   354 {
   355   switch(e->type)
   356   {
   357     case GDK_BUTTON_PRESS:
   358       //we mark the location of the event to be able to calculate parameters of dragging
   359       clicked_x=e->button.x;
   360       clicked_y=e->button.y;
   361       active_item=(get_item_at(e->button.x, e->button.y));
   362       active_node=INVALID;
   363       for (NodeIt i(g); i!=INVALID; ++i)
   364 	{
   365 	  if(nodesmap[i]==active_item)
   366 	    {
   367 	      active_node=i;
   368 	    }
   369 	}
   370       switch(e->button.button)
   371 	{
   372 	case 3:      
   373 	  isbutton=3;
   374 	  break;
   375 	default:
   376 	  isbutton=1;
   377 	  break;
   378 	}
   379       break;
   380     case GDK_BUTTON_RELEASE:
   381       isbutton=0;
   382       active_item=NULL;
   383       active_node=INVALID;
   384       updateScrollRegion();
   385       break;
   386     case GDK_MOTION_NOTIFY:
   387       //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
   388       if(active_node!=INVALID)
   389       {
   390 	//new coordinates will be the old values,
   391 	//because the item will be moved to the
   392 	//new coordinate therefore the new movement
   393 	//has to be calculated from here
   394 
   395         double dx=e->motion.x-clicked_x;
   396         double dy=e->motion.y-clicked_y;
   397 
   398         active_item->move(dx, dy);
   399 
   400         clicked_x=e->motion.x;
   401         clicked_y=e->motion.y;
   402 
   403 	//all the edges connected to the moved point has to be redrawn
   404         EdgeIt ei;
   405 
   406         g.firstOut(ei,active_node);
   407 
   408         for(;ei!=INVALID;g.nextOut(ei))
   409         {
   410             Gnome::Canvas::Points coos;
   411             double x1, x2, y1, y2;
   412 
   413             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   414             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   415 
   416             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   417             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   418 
   419 	    if(isbutton==3)
   420 	      {
   421 		edgesmap[ei]->set_points(coos);
   422 	      }
   423 	    else
   424 	      {
   425 		edgesmap[ei]->set_points(coos,true);
   426 	      }
   427 
   428 	    xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
   429 	    text_pos+=(xy<double>(10,10));
   430 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   431 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   432         }
   433 
   434         g.firstIn(ei,active_node);
   435         for(;ei!=INVALID;g.nextIn(ei))
   436         {
   437             Gnome::Canvas::Points coos;
   438             double x1, x2, y1, y2;
   439 
   440             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   441             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   442 
   443             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   444             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   445 
   446 	    if(isbutton==3)
   447 	      {
   448 		edgesmap[ei]->set_points(coos);
   449 	      }
   450 	    else
   451 	      {
   452 		edgesmap[ei]->set_points(coos,true);
   453 	      }
   454 
   455 	    xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
   456 	    text_pos+=(xy<double>(10,10));
   457 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   458 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   459         }
   460       }
   461     default: break;
   462   }
   463 
   464   return true;
   465 }
   466 
   467 bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
   468 {
   469   switch(e->type)
   470     {
   471 
   472       //draw the new node in red at the clicked place
   473     case GDK_BUTTON_PRESS:
   474       isbutton=1;
   475 
   476       active_node=NodeIt(g,g.addNode());
   477 
   478       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   479 
   480       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   481       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   482       *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   483       *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
   484       (nodesmap[active_node])->show();
   485       break;
   486 
   487       //move the new node
   488     case GDK_MOTION_NOTIFY:
   489       {
   490 	double world_motion_x, world_motion_y;
   491 	GdkEvent * generated=new GdkEvent();
   492 	window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
   493 	generated->motion.x=world_motion_x;
   494 	generated->motion.y=world_motion_y;
   495 	generated->type=GDK_MOTION_NOTIFY;
   496 	move_event_handler(generated);      
   497 	break;
   498       }
   499 
   500       //finalize the new node
   501     case GDK_BUTTON_RELEASE:
   502       isbutton=0;
   503       *active_item << Gnome::Canvas::Properties::fill_color("blue");
   504       active_item=NULL;
   505       active_node=INVALID;
   506       updateScrollRegion();
   507       break;
   508     default:
   509       break;
   510     }
   511   return false;
   512 }
   513 
   514 bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
   515 {
   516   switch(e->type)
   517     {
   518     case GDK_BUTTON_PRESS:
   519       //in edge creatino right button has special meaning
   520       if(e->button.button!=3)
   521 	{
   522 	  //there is not yet selected node
   523 	  if(active_node==INVALID)
   524 	    {
   525 	      //we mark the location of the event to be able to calculate parameters of dragging
   526 	      clicked_x=e->button.x;
   527 	      clicked_y=e->button.y;
   528 	      active_item=(get_item_at(e->button.x, e->button.y));
   529 	      active_node=INVALID;
   530 	      for (NodeIt i(g); i!=INVALID; ++i)
   531 		{
   532 		  if(nodesmap[i]==active_item)
   533 		    {
   534 		      active_node=i;
   535 		    }
   536 		}
   537 	      //the clicked item is really a node
   538 	      if(active_node!=INVALID)
   539 		{
   540 		  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   541 		  isbutton=1;
   542 		}
   543 	      //clicked item was not a node. It could be e.g. edge.
   544 	      else
   545 		{
   546 		  active_item=NULL;
   547 		}
   548 	    }
   549 	  //we only have to do sg. if the mouse button
   550 	  // is pressed already once AND the click was
   551 	  // on a node that was found in the set of 
   552 	  //nodes, and now we only search for the second 
   553 	  //node
   554 	  else
   555 	    {
   556 	      target_item=(get_item_at(e->button.x, e->button.y));
   557 	      Graph::NodeIt target_node=INVALID;
   558 	      for (NodeIt i(g); i!=INVALID; ++i)
   559 		{
   560 		  if(nodesmap[i]==target_item)
   561 		    {
   562 		      target_node=i;
   563 		    }
   564 		}
   565 	      //the clicked item is a node, the edge can be drawn
   566 	      if(target_node!=INVALID)
   567 		{
   568 		  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   569 
   570 		  //creating new edge
   571 		  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   572 	  
   573 		  //calculating coordinates of new edge
   574 		  Gnome::Canvas::Points coos;
   575 		  double x1, x2, y1, y2;
   576 	  
   577 		  active_item->get_bounds(x1, y1, x2, y2);
   578 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   579 
   580 		  target_item->get_bounds(x1, y1, x2, y2);
   581 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   582 
   583 		  //drawing new edge
   584 		  edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
   585 		  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   586 		  edgesmap[active_edge]->property_width_pixels().set_value(10);
   587 
   588 		  //redraw nodes to blank terminations of the new edge
   589 		  target_item->raise_to_top();
   590 		  active_item->raise_to_top();
   591 
   592 		  //initializing edge-text as well, to empty string
   593 		  xy<double> text_pos=edgesmap[active_edge]->get_arrow_pos();
   594 		  text_pos+=(xy<double>(10,10));
   595 
   596 		  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
   597 		  edgetextmap[active_edge]->property_fill_color().set_value("black");
   598 		}
   599 	      //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
   600 	      else
   601 		{
   602 		  target_item=NULL;
   603 		}
   604 	    }
   605 	}
   606       break;
   607     case GDK_BUTTON_RELEASE:
   608       isbutton=0;
   609       //we clear settings in two cases
   610       //1: the edge is ready (target_item has valid value)
   611       //2: the edge creation is cancelled with right button
   612       if((target_item)||(e->button.button==3))
   613 	{
   614 	  if(active_item)
   615 	    {
   616 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   617 	      active_item=NULL;
   618 	    }
   619 	  if(target_item)
   620 	    {
   621 	      *target_item << Gnome::Canvas::Properties::fill_color("blue");
   622 	      target_item=NULL;
   623 	    }
   624 	  active_node=INVALID;
   625 	  active_edge=INVALID;
   626 	}
   627       break;
   628     default:
   629       break;
   630     }
   631   return false;
   632 }
   633 
   634 bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
   635 {
   636   switch(e->type)
   637     {
   638     case GDK_BUTTON_PRESS:
   639       active_item=(get_item_at(e->button.x, e->button.y));
   640       active_node=INVALID;
   641       active_edge=INVALID;
   642       for (NodeIt i(g); i!=INVALID; ++i)
   643 	{
   644 	  if(nodesmap[i]==active_item)
   645 	    {
   646 	      active_node=i;
   647 	    }
   648 	}
   649       if(active_node==INVALID)
   650 	{
   651 	  for (EdgeIt i(g); i!=INVALID; ++i)
   652 	    {
   653 	      if(edgesmap[i]==active_item)
   654 		{
   655 		  active_edge=i;
   656 		}
   657 	    }
   658 	}
   659     *active_item << Gnome::Canvas::Properties::fill_color("red");
   660       break;
   661 
   662     case GDK_BUTTON_RELEASE:
   663       if(active_item==(get_item_at(e->button.x, e->button.y)))
   664 	{
   665 	  if(active_node!=INVALID)
   666 	    {
   667 
   668 	      //collecting edges to delete
   669 	      EdgeIt e;
   670 	      std::set<Graph::Edge> edges_to_delete;
   671 
   672 	      g.firstOut(e,active_node);
   673 	      for(;e!=INVALID;g.nextOut(e))
   674 		{
   675 		      edges_to_delete.insert(e);
   676 		}
   677 
   678 	      g.firstIn(e,active_node);
   679 	      for(;e!=INVALID;g.nextIn(e))
   680 		{
   681 		      edges_to_delete.insert(e);
   682 		}
   683 
   684 	      //deleting collected edges
   685 	      for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
   686 		{
   687 		  delete_item(*edge_set_it);
   688 		}
   689 	      delete_item(active_node);
   690 	    }
   691 	  //a simple edge was chosen
   692 	  else
   693 	    {
   694 	      delete_item(active_edge);
   695 	    }
   696 
   697 	  
   698 	}
   699       //pointer was moved, deletion is cancelled
   700       else
   701 	{
   702 	  if(active_node!=INVALID)
   703 	    {
   704 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   705 	    }
   706 	  else
   707 	    {
   708 	      *active_item << Gnome::Canvas::Properties::fill_color("green");
   709 	    }
   710 	}
   711       //reseting datas
   712       active_item=NULL;
   713       active_edge=INVALID;
   714       active_node=INVALID;
   715       break;
   716 
   717     case GDK_MOTION_NOTIFY:
   718       break;
   719 
   720     default:
   721       break;
   722     }
   723   return true;
   724 }
   725 
   726 void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
   727 {
   728   delete(nodesmap[node_to_delete]);
   729   g.erase(node_to_delete);
   730 }
   731 
   732 void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
   733 {
   734   delete(edgesmap[edge_to_delete]);
   735   g.erase(edge_to_delete);
   736 }
   737 
   738 void GraphDisplayerCanvas::delete_item(Graph::Edge edge_to_delete)
   739 {
   740   delete(edgesmap[edge_to_delete]);
   741   g.erase(edge_to_delete);
   742 }
   743 
   744 void GraphDisplayerCanvas::text_reposition(xy<double> new_place)
   745 {
   746   new_place+=(xy<double>(10,10));
   747   edgetextmap[active_edge]->property_x().set_value(new_place.x);
   748   edgetextmap[active_edge]->property_y().set_value(new_place.y);
   749 }
   750 
   751 void GraphDisplayerCanvas::toggle_edge_activity(BrokenEdge* active_bre, bool on)
   752 {
   753   if(on)
   754     {
   755       if(active_edge!=INVALID)
   756 	{
   757 	  std::cout << "ERROR!!!! Valid edge found!" << std::endl;
   758 	}
   759       else
   760 	{
   761 	  for (EdgeIt i(g); i!=INVALID; ++i)
   762 	    {
   763 	      if(edgesmap[i]==active_bre)
   764 		{
   765 		  active_edge=i;
   766 		}
   767 	    }
   768 	}
   769     }
   770   else
   771     {
   772       if(active_edge!=INVALID)
   773 	{
   774 	  active_edge=INVALID;
   775 	}
   776       else
   777 	{
   778 	  std::cout << "ERROR!!!! Invalid edge found!" << std::endl;
   779 	}
   780     }
   781 
   782 }