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