gui/graph_displayer_canvas-event.cc
author deba
Fri, 28 Oct 2005 09:01:59 +0000
changeset 1747 bccf2379b5dd
parent 1652 6eb2f0f3bab9
child 1777 a70cee06ae9c
permissions -rwxr-xr-x
Faster implementation
     1 #include "graph_displayer_canvas.h"
     2 #include "broken_edge.h"
     3 #include <cmath>
     4 
     5 
     6 bool 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 
    14 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
    15 {
    16   if(actual_tool!=newtool)
    17     {
    18 
    19       actual_handler.disconnect();
    20 
    21       switch(actual_tool)
    22 	{
    23 	case CREATE_EDGE:
    24 	  {
    25 	    GdkEvent * generated=new GdkEvent();
    26 	    generated->type=GDK_BUTTON_RELEASE;
    27 	    generated->button.button=3;
    28 	    createEdgeEventHandler(generated);      
    29 	    break;
    30 	  }
    31 	case EDGE_MAP_EDIT:
    32 	  //has to do the same thing as in the case of NODE_MAP_EDIT
    33 	case NODE_MAP_EDIT:
    34 	  {
    35 	    break;
    36 	  }
    37 	default:
    38 	  break;
    39 	}
    40 
    41       active_item=NULL; 
    42       target_item=NULL; 
    43       active_edge=INVALID;	
    44       active_node=INVALID;	
    45 
    46 
    47       actual_tool=newtool;
    48   
    49       switch(newtool)
    50 	{
    51 	case MOVE:
    52 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
    53 	  break;
    54 
    55 	case CREATE_NODE:
    56 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
    57 	  break;
    58 
    59 	case CREATE_EDGE:
    60 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
    61 	  break;
    62 
    63 	case ERASER:
    64 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
    65 	  break;
    66 
    67 	case EDGE_MAP_EDIT:
    68 	  grab_focus();
    69 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
    70 	  break;
    71 
    72 	case NODE_MAP_EDIT:
    73 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
    74 	  break;
    75 
    76 	default:
    77 	  break;
    78 	}
    79     }
    80 }
    81 
    82 int GraphDisplayerCanvas::getActualTool()
    83 {
    84   return actual_tool;
    85 }
    86 
    87 bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
    88 {
    89   static Gnome::Canvas::Text *coord_text = 0;
    90   switch(e->type)
    91   {
    92     case GDK_BUTTON_PRESS:
    93       //we mark the location of the event to be able to calculate parameters of dragging
    94       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
    95 
    96       active_item=(get_item_at(clicked_x, clicked_y));
    97       active_node=INVALID;
    98       for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
    99 	{
   100 	  if(nodesmap[i]==active_item)
   101 	    {
   102 	      active_node=i;
   103 	    }
   104 	}
   105       switch(e->button.button)
   106 	{
   107 	case 3:      
   108 	  isbutton=3;
   109 	  break;
   110 	default:
   111 	  isbutton=1;
   112 	  break;
   113 	}
   114       break;
   115     case GDK_BUTTON_RELEASE:
   116       if (coord_text)
   117       {
   118         delete coord_text;
   119         coord_text = 0;
   120       }
   121       isbutton=0;
   122       active_item=NULL;
   123       active_node=INVALID;
   124       break;
   125     case GDK_MOTION_NOTIFY:
   126       //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
   127       if(active_node!=INVALID)
   128       {
   129         mapstorage.modified = true;
   130 
   131 	//new coordinates will be the old values,
   132 	//because the item will be moved to the
   133 	//new coordinate therefore the new movement
   134 	//has to be calculated from here
   135 
   136 	double new_x, new_y;
   137 
   138 	window_to_world (e->motion.x, e->motion.y, new_x, new_y);
   139 
   140         double dx=new_x-clicked_x;
   141         double dy=new_y-clicked_y;
   142 
   143 	//repositioning node and its text
   144         active_item->move(dx, dy);
   145 	nodetextmap[active_node]->move(dx, dy);
   146 
   147         // the new coordinates of the centre of the node 
   148         double coord_x = new_x - (clicked_x - mapstorage.coords[active_node].x);
   149         double coord_y = new_y - (clicked_y - mapstorage.coords[active_node].y);
   150 
   151         clicked_x=new_x;
   152         clicked_y=new_y;
   153 
   154         // write back the new coordinates to the coords map
   155         mapstorage.coords.set(active_node, xy<double>(coord_x, coord_y));
   156 
   157         // reposition the coordinates text
   158         std::ostringstream ostr;
   159         ostr << "(" <<
   160           mapstorage.coords[active_node].x << ", " <<
   161           mapstorage.coords[active_node].y << ")";
   162         double radius =
   163           (nodesmap[active_node]->property_x2().get_value() -
   164           nodesmap[active_node]->property_x1().get_value()) / 2.0;
   165         if (coord_text)
   166         {
   167           coord_text->property_text().set_value(ostr.str());
   168           coord_text->property_x().set_value(mapstorage.coords[active_node].x +
   169               radius);
   170           coord_text->property_y().set_value(mapstorage.coords[active_node].y -
   171               radius);
   172         }
   173         else
   174         {
   175           coord_text = new Gnome::Canvas::Text(
   176               displayed_graph,
   177               mapstorage.coords[active_node].x + radius,
   178               mapstorage.coords[active_node].y - radius,
   179               ostr.str());
   180           coord_text->property_fill_color().set_value("black");
   181           coord_text->property_anchor().set_value(Gtk::ANCHOR_SOUTH_WEST);
   182         }
   183 
   184 	//all the edges connected to the moved point has to be redrawn
   185         for(OutEdgeIt ei(mapstorage.graph,active_node);ei!=INVALID;++ei)
   186         {
   187             Gnome::Canvas::Points coos;
   188             double x1, x2, y1, y2;
   189 
   190             nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
   191             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   192 
   193             nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
   194             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   195 
   196 	    if(isbutton==3)
   197 	      {
   198 		edgesmap[ei]->setPoints(coos);
   199 	      }
   200 	    else
   201 	      {
   202 		edgesmap[ei]->setPoints(coos,true);
   203 	      }
   204 
   205 	    //reposition of edgetext
   206 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   207 	    text_pos+=(xy<double>(10,10));
   208 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   209 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   210         }
   211 
   212         for(InEdgeIt ei(mapstorage.graph,active_node);ei!=INVALID;++ei)
   213         {
   214             Gnome::Canvas::Points coos;
   215             double x1, x2, y1, y2;
   216 
   217             nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
   218             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   219 
   220             nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
   221             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   222 
   223 	    if(isbutton==3)
   224 	      {
   225 		edgesmap[ei]->setPoints(coos);
   226 	      }
   227 	    else
   228 	      {
   229 		edgesmap[ei]->setPoints(coos,true);
   230 	      }
   231 
   232 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   233 	    text_pos+=(xy<double>(10,10));
   234 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   235 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   236         }
   237       }
   238     default: break;
   239   }
   240 
   241   return false;
   242 }
   243 
   244 bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
   245 {
   246   switch(e->type)
   247   {
   248     //move the new node
   249     case GDK_MOTION_NOTIFY:
   250       {
   251         GdkEvent * generated=new GdkEvent();
   252         generated->motion.x=e->motion.x;
   253         generated->motion.y=e->motion.y;
   254         generated->type=GDK_MOTION_NOTIFY;
   255         moveEventHandler(generated);      
   256         break;
   257       }
   258 
   259     case GDK_BUTTON_RELEASE:
   260       mapstorage.modified = true;
   261 
   262       isbutton=1;
   263 
   264       active_node=mapstorage.graph.addNode();
   265 
   266       //initiating values corresponding to new node in maps
   267 
   268       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   269 
   270       // update coordinates
   271       mapstorage.coords.set(active_node, xy<double>(clicked_x, clicked_y));
   272 
   273       // update all other maps
   274       for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
   275           mapstorage.nodemap_storage.begin(); it !=
   276           mapstorage.nodemap_storage.end(); ++it)
   277       {
   278         if ((it->first != "coordinates_x") &&
   279             (it->first != "coordinates_y"))
   280         {
   281           (*(it->second))[active_node] =
   282             mapstorage.nodemap_default[it->first];
   283         }
   284       }
   285       // increment the id map's default value
   286       mapstorage.nodemap_default["id"] += 1.0;
   287 
   288       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph,
   289           clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   290       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   291       *(nodesmap[active_node]) <<
   292         Gnome::Canvas::Properties::fill_color("blue");
   293       *(nodesmap[active_node]) <<
   294         Gnome::Canvas::Properties::outline_color("black");
   295       active_item->raise_to_top();
   296 
   297       (nodesmap[active_node])->show();
   298 
   299       nodetextmap[active_node]=new Gnome::Canvas::Text(displayed_graph,
   300           clicked_x+node_property_defaults[N_RADIUS]+5,
   301           clicked_y+node_property_defaults[N_RADIUS]+5, "");
   302       nodetextmap[active_node]->property_fill_color().set_value("darkblue");
   303       nodetextmap[active_node]->raise_to_top();
   304 
   305       mapwin.updateNode(active_node);
   306 
   307       isbutton=0;
   308       target_item=NULL;
   309       active_item=NULL;
   310       active_node=INVALID;
   311 
   312       break;
   313     default:
   314       break;
   315   }
   316   return false;
   317 }
   318 
   319 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
   320 {
   321   switch(e->type)
   322   {
   323     case GDK_BUTTON_PRESS:
   324       //in edge creation right button has special meaning
   325       if(e->button.button!=3)
   326       {
   327         //there is not yet selected node
   328         if(active_node==INVALID)
   329         {
   330           //we mark the location of the event to be able to calculate parameters of dragging
   331 
   332           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   333 
   334           active_item=(get_item_at(clicked_x, clicked_y));
   335           active_node=INVALID;
   336           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   337           {
   338             if(nodesmap[i]==active_item)
   339             {
   340               active_node=i;
   341             }
   342           }
   343           //the clicked item is really a node
   344           if(active_node!=INVALID)
   345           {
   346             *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   347             isbutton=1;
   348           }
   349           //clicked item was not a node. It could be e.g. edge.
   350           else
   351           {
   352             active_item=NULL;
   353           }
   354         }
   355         //we only have to do sg. if the mouse button
   356         // is pressed already once AND the click was
   357         // on a node that was found in the set of 
   358         //nodes, and now we only search for the second 
   359         //node
   360         else
   361         {
   362           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   363           target_item=(get_item_at(clicked_x, clicked_y));
   364           Node target_node=INVALID;
   365           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   366           {
   367             if(nodesmap[i]==target_item)
   368             {
   369               target_node=i;
   370             }
   371           }
   372           //the clicked item is a node, the edge can be drawn
   373           if(target_node!=INVALID)
   374           {
   375             if(target_node!=active_node)		
   376             {
   377               mapstorage.modified = true;
   378 
   379               *(nodesmap[target_node]) <<
   380                 Gnome::Canvas::Properties::fill_color("red");
   381 
   382               //creating new edge
   383               active_edge=mapstorage.graph.addEdge(active_node,
   384                   target_node);
   385 
   386               // update maps
   387               for (std::map<std::string,
   388                   Graph::EdgeMap<double>*>::const_iterator it =
   389                   mapstorage.edgemap_storage.begin(); it !=
   390                   mapstorage.edgemap_storage.end(); ++it)
   391               {
   392                 (*(it->second))[active_edge] =
   393                   mapstorage.edgemap_default[it->first];
   394               }
   395               // increment the id map's default value
   396               mapstorage.edgemap_default["id"] += 1.0;
   397 
   398               //calculating coordinates of new edge
   399               Gnome::Canvas::Points coos;
   400               double x1, x2, y1, y2;
   401 
   402               active_item->get_bounds(x1, y1, x2, y2);
   403               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   404 
   405               target_item->get_bounds(x1, y1, x2, y2);
   406               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   407 
   408               //drawing new edge
   409               edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos,
   410                   *this);
   411               *(edgesmap[active_edge]) <<
   412                 Gnome::Canvas::Properties::fill_color("green");
   413               edgesmap[active_edge]->property_width_pixels().set_value(10);
   414 
   415               edgesmap[active_edge]->lower_to_bottom();
   416 
   417               //initializing edge-text as well, to empty string
   418               xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
   419               text_pos+=(xy<double>(10,10));
   420 
   421               edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
   422                   text_pos.x, text_pos.y, "");
   423               edgetextmap[active_edge]->property_fill_color().set_value(
   424                   "darkgreen");
   425               edgetextmap[active_edge]->raise_to_top();
   426 
   427               //updating its properties
   428               mapwin.updateEdge(active_edge);
   429             }
   430             else
   431             {
   432               target_node=INVALID;
   433               std::cerr << "Loop edge is not yet implemented!" << std::endl;
   434             }
   435           }
   436           //clicked item was not a node. it could be an e.g. edge. we do not
   437           //deal with it furthermore.
   438           else
   439           {
   440             target_item=NULL;
   441           }
   442         }
   443       }
   444       break;
   445     case GDK_BUTTON_RELEASE:
   446       isbutton=0;
   447       //we clear settings in two cases
   448       //1: the edge is ready (target_item has valid value)
   449       //2: the edge creation is cancelled with right button
   450       if((target_item)||(e->button.button==3))
   451       {
   452         if(active_item)
   453         {
   454           *active_item << Gnome::Canvas::Properties::fill_color("blue");
   455           active_item=NULL;
   456         }
   457         if(target_item)
   458         {
   459           *target_item << Gnome::Canvas::Properties::fill_color("blue");
   460           target_item=NULL;
   461         }
   462         active_node=INVALID;
   463         active_edge=INVALID;
   464       }
   465       break;
   466     default:
   467       break;
   468   }
   469   return false;
   470 }
   471 
   472 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
   473 {
   474   switch(e->type)
   475     {
   476     case GDK_BUTTON_PRESS:
   477       //finding the clicked items
   478       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   479       active_item=(get_item_at(clicked_x, clicked_y));
   480       active_node=INVALID;
   481       active_edge=INVALID;
   482       //was it a node?
   483       for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   484 	{
   485 	  if(nodesmap[i]==active_item)
   486 	    {
   487 	      active_node=i;
   488 	    }
   489 	}
   490       //or was it an edge?
   491       if(active_node==INVALID)
   492 	{
   493 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   494 	    {
   495 	      if(edgesmap[i]==active_item)
   496 		{
   497 		  active_edge=i;
   498 		}
   499 	    }
   500 	}
   501 
   502       //recolor activated item
   503       if(active_item)
   504 	{
   505 	  *active_item << Gnome::Canvas::Properties::fill_color("red");
   506 	}
   507       break;
   508 
   509     case GDK_BUTTON_RELEASE:
   510       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   511       if(active_item)
   512 	{
   513 	  //the cursor was not moved since pressing it
   514 	  if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
   515 	    {
   516 	      //a node was found
   517 	      if(active_node!=INVALID)
   518 		{
   519                   mapstorage.modified = true;
   520 
   521 		  std::set<Graph::Edge> edges_to_delete;
   522 
   523 		  for(OutEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
   524 		    {
   525 		      edges_to_delete.insert(e);
   526 		    }
   527 		  
   528 		  for(InEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
   529 		    {
   530 		      edges_to_delete.insert(e);
   531 		    }
   532 		  
   533 		  //deleting collected edges
   534 		  for(std::set<Graph::Edge>::iterator
   535 			edge_set_it=edges_to_delete.begin();
   536 		      edge_set_it!=edges_to_delete.end();
   537 		      ++edge_set_it)
   538 		    {
   539 		      deleteItem(*edge_set_it);
   540 		    }
   541 		  deleteItem(active_node);
   542 		}
   543 	      //a simple edge was chosen
   544 	      else
   545 		{
   546 		  deleteItem(active_edge);
   547 		}
   548 	    }
   549 	  //pointer was moved, deletion is cancelled
   550 	  else
   551 	    {
   552 	      if(active_node!=INVALID)
   553 		{
   554 		  *active_item << Gnome::Canvas::Properties::fill_color("blue");
   555 		}
   556 	      else
   557 		{
   558 		  *active_item << Gnome::Canvas::Properties::fill_color("green");
   559 		}
   560 	    }
   561 	}
   562       //reseting datas
   563       active_item=NULL;
   564       active_edge=INVALID;
   565       active_node=INVALID;
   566       break;
   567 
   568     case GDK_MOTION_NOTIFY:
   569       break;
   570 
   571     default:
   572       break;
   573     }
   574   return false;
   575 }
   576 
   577 bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
   578 {
   579   if(actual_tool==EDGE_MAP_EDIT)
   580   {
   581     switch(e->type)
   582     {
   583       case GDK_BUTTON_PRESS:
   584         {
   585           //for determine, whether it was an edge
   586           Edge clicked_edge=INVALID;
   587 
   588           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   589           active_item=(get_item_at(clicked_x, clicked_y));
   590 
   591           //find the activated item between texts
   592           for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   593           {
   594             //at the same time only one can be active
   595             if(edgetextmap[i]==active_item)
   596             {
   597               clicked_edge=i;
   598             }
   599           }
   600 
   601           //if it was not between texts, search for it between edges
   602           if(clicked_edge==INVALID)
   603           {
   604             for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   605             {
   606               //at the same time only one can be active
   607               if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
   608               {
   609                 clicked_edge=i;
   610               }
   611             }
   612           }
   613  
   614           //if it was really an edge...
   615           if(clicked_edge!=INVALID)
   616           {
   617             // the id map is not editable
   618             if (edgemap_to_edit == "id") return 0;
   619 
   620             //and there is activated map
   621             if(edgetextmap[clicked_edge]->property_text().get_value()!="")
   622             {
   623               //activate the general variable for it
   624               active_edge=clicked_edge;
   625 
   626               //create a dialog
   627               Gtk::Dialog dialog("Edit value", *parentwin, true);
   628               dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   629               dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   630               Gtk::VBox* vbox = dialog.get_vbox();
   631               Gtk::Adjustment adj(
   632                   (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge],
   633                   -1000000.0,
   634                   1000000.0,
   635                   1.0, 5.0, 0.0);
   636               //TODO: find out why doesn't it work with
   637               //numeric_limits<double>::min/max
   638               Gtk::SpinButton spin(adj);
   639               spin.set_numeric(true);
   640               spin.set_digits(4);
   641               vbox->add(spin);
   642               spin.show();
   643               switch (dialog.run())
   644               {
   645                 case Gtk::RESPONSE_NONE:
   646                 case Gtk::RESPONSE_CANCEL:
   647                   break;
   648                 case Gtk::RESPONSE_ACCEPT:
   649                   double new_value = spin.get_value();
   650                   (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge] =
   651                     new_value;
   652                   std::ostringstream ostr;
   653                   ostr << new_value;
   654                   edgetextmap[active_edge]->property_text().set_value(
   655                       ostr.str());
   656                   //mapwin.updateEdge(active_edge);
   657                   mapwin.updateEdge(Edge(INVALID));
   658               }
   659             }
   660           }
   661           break;
   662         }
   663       default:
   664         break;
   665     }
   666   }
   667   return false;  
   668 }
   669 
   670 bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
   671 {
   672   if(actual_tool==NODE_MAP_EDIT)
   673   {
   674     switch(e->type)
   675     {
   676       case GDK_BUTTON_PRESS:
   677         {
   678           //for determine, whether it was a node
   679           Node clicked_node=INVALID;
   680 
   681           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   682           active_item=(get_item_at(clicked_x, clicked_y));
   683 
   684           //find the activated item between texts
   685           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   686           {
   687             //at the same time only one can be active
   688             if(nodetextmap[i]==active_item)
   689             {
   690               clicked_node=i;
   691             }
   692           }
   693 
   694           //if there was not, search for it between nodes
   695           if(clicked_node==INVALID)
   696           {
   697             for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   698             {
   699               //at the same time only one can be active
   700               if(nodesmap[i]==active_item)
   701               {
   702                 clicked_node=i;
   703               }
   704             }
   705           }
   706 
   707           //if it was really a node...
   708           if(clicked_node!=INVALID)
   709           {
   710             // the id map is not editable
   711             if (nodemap_to_edit == "id") return 0;
   712 
   713             //and there is activated map
   714             if(nodetextmap[clicked_node]->property_text().get_value()!="")
   715             {
   716               //activate the general variable for it
   717               active_node=clicked_node;
   718 
   719               //create a dialog
   720               Gtk::Dialog dialog("Edit value", *parentwin, true);
   721               dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   722               dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   723               Gtk::VBox* vbox = dialog.get_vbox();
   724               Gtk::Adjustment adj(
   725                   (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node],
   726                   -1000000.0,
   727                   1000000.0,
   728                   1.0, 5.0, 0.0);
   729               //TODO: find out why doesn't it work with
   730               //numeric_limits<double>::min/max
   731               Gtk::SpinButton spin(adj);
   732               spin.set_numeric(true);
   733               spin.set_digits(4);
   734               vbox->add(spin);
   735               spin.show();
   736               switch (dialog.run())
   737               {
   738                 case Gtk::RESPONSE_NONE:
   739                 case Gtk::RESPONSE_CANCEL:
   740                   break;
   741                 case Gtk::RESPONSE_ACCEPT:
   742                   double new_value = spin.get_value();
   743                   (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node] =
   744                     new_value;
   745                   std::ostringstream ostr;
   746                   ostr << new_value;
   747                   nodetextmap[active_node]->property_text().set_value(
   748                       ostr.str());
   749                   //mapwin.updateNode(active_node);
   750                   mapwin.updateNode(Node(INVALID));
   751               }
   752             }
   753           }
   754           break;
   755         }
   756       default:
   757         break;
   758     }
   759   }
   760   return false;  
   761 }
   762 
   763 void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
   764 {
   765   delete(nodetextmap[node_to_delete]);
   766   delete(nodesmap[node_to_delete]);
   767   mapstorage.graph.erase(node_to_delete);
   768 }
   769 
   770 void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
   771 {
   772   delete(edgetextmap[edge_to_delete]);
   773   delete(edgesmap[edge_to_delete]);
   774   mapstorage.graph.erase(edge_to_delete);
   775 }
   776 
   777 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
   778 {
   779   new_place+=(xy<double>(10,10));
   780   edgetextmap[forming_edge]->property_x().set_value(new_place.x);
   781   edgetextmap[forming_edge]->property_y().set_value(new_place.y);
   782 }
   783 
   784 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
   785 {
   786   if(on)
   787     {
   788       if(forming_edge!=INVALID)
   789 	{
   790 	  std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
   791 	}
   792       else
   793 	{
   794 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   795 	    {
   796 	      if(edgesmap[i]==active_bre)
   797 		{
   798 		  forming_edge=i;
   799 		}
   800 	    }
   801 	}
   802     }
   803   else
   804     {
   805       if(forming_edge!=INVALID)
   806 	{
   807 	  forming_edge=INVALID;
   808 	}
   809       else
   810 	{
   811 	  std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
   812 	}
   813     }
   814 
   815 }
   816 
   817 int GraphDisplayerCanvas::addNewEdgeMap(double default_value, std::string mapname)
   818 {
   819   //create the new map
   820   Graph::EdgeMap<double> * emptr=new Graph::EdgeMap<double> (mapstorage.graph, default_value);
   821 
   822   //if addition was not successful addEdgeMap returns one.
   823   //cause can be that there is already a map named like the new one
   824   if(mapstorage.addEdgeMap(mapname,emptr, default_value))
   825     {
   826       return 1;
   827     }
   828 
   829 
   830   //add it to the list of the displayable maps
   831   mapwin.registerNewEdgeMap(mapname);
   832 
   833   //display it
   834   changeEdgeText(mapname);
   835 
   836   return 0;
   837 }
   838 
   839 int GraphDisplayerCanvas::addNewNodeMap(double default_value, std::string mapname)
   840 {
   841   //create the new map
   842   Graph::NodeMap<double> * emptr=new Graph::NodeMap<double> (mapstorage.graph,default_value);
   843 
   844   //if addition was not successful addNodeMap returns one.
   845   //cause can be that there is already a map named like the new one
   846   if(mapstorage.addNodeMap(mapname,emptr, default_value))
   847     {
   848       return 1;
   849     }
   850 
   851   //add it to the list of the displayable maps
   852   mapwin.registerNewNodeMap(mapname);
   853 
   854   //display it
   855   changeNodeText(mapname);
   856 
   857   return 0;
   858 }
   859