graph_displayer_canvas-event.cc
author ladanyi
Fri, 04 Nov 2005 19:07:15 +0000
branchgui
changeset 87 b44281e4cca7
parent 72 ebde44fded74
child 89 4042761b21e3
permissions -rwxr-xr-x
improved zooming
     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       break;
   312     default:
   313       break;
   314   }
   315   return false;
   316 }
   317 
   318 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
   319 {
   320   switch(e->type)
   321   {
   322     case GDK_BUTTON_PRESS:
   323       //in edge creation right button has special meaning
   324       if(e->button.button!=3)
   325       {
   326         //there is not yet selected node
   327         if(active_node==INVALID)
   328         {
   329           //we mark the location of the event to be able to calculate parameters of dragging
   330 
   331           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   332 
   333           active_item=(get_item_at(clicked_x, clicked_y));
   334           active_node=INVALID;
   335           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   336           {
   337             if(nodesmap[i]==active_item)
   338             {
   339               active_node=i;
   340             }
   341           }
   342           //the clicked item is really a node
   343           if(active_node!=INVALID)
   344           {
   345             *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   346             isbutton=1;
   347           }
   348           //clicked item was not a node. It could be e.g. edge.
   349           else
   350           {
   351             active_item=NULL;
   352           }
   353         }
   354         //we only have to do sg. if the mouse button
   355         // is pressed already once AND the click was
   356         // on a node that was found in the set of 
   357         //nodes, and now we only search for the second 
   358         //node
   359         else
   360         {
   361           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   362           target_item=(get_item_at(clicked_x, clicked_y));
   363           Node target_node=INVALID;
   364           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   365           {
   366             if(nodesmap[i]==target_item)
   367             {
   368               target_node=i;
   369             }
   370           }
   371           //the clicked item is a node, the edge can be drawn
   372           if(target_node!=INVALID)
   373           {
   374             if(target_node!=active_node)		
   375             {
   376               mapstorage.modified = true;
   377 
   378               *(nodesmap[target_node]) <<
   379                 Gnome::Canvas::Properties::fill_color("red");
   380 
   381               //creating new edge
   382               active_edge=mapstorage.graph.addEdge(active_node,
   383                   target_node);
   384 
   385               // update maps
   386               for (std::map<std::string,
   387                   Graph::EdgeMap<double>*>::const_iterator it =
   388                   mapstorage.edgemap_storage.begin(); it !=
   389                   mapstorage.edgemap_storage.end(); ++it)
   390               {
   391                 (*(it->second))[active_edge] =
   392                   mapstorage.edgemap_default[it->first];
   393               }
   394               // increment the id map's default value
   395               mapstorage.edgemap_default["id"] += 1.0;
   396 
   397               //calculating coordinates of new edge
   398               Gnome::Canvas::Points coos;
   399               double x1, x2, y1, y2;
   400 
   401               active_item->get_bounds(x1, y1, x2, y2);
   402               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   403 
   404               target_item->get_bounds(x1, y1, x2, y2);
   405               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   406 
   407               //drawing new edge
   408               edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos,
   409                   *this);
   410               *(edgesmap[active_edge]) <<
   411                 Gnome::Canvas::Properties::fill_color("green");
   412               edgesmap[active_edge]->property_width_pixels().set_value(10);
   413 
   414               edgesmap[active_edge]->lower_to_bottom();
   415 
   416               //initializing edge-text as well, to empty string
   417               xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
   418               text_pos+=(xy<double>(10,10));
   419 
   420               edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
   421                   text_pos.x, text_pos.y, "");
   422               edgetextmap[active_edge]->property_fill_color().set_value(
   423                   "darkgreen");
   424               edgetextmap[active_edge]->raise_to_top();
   425 
   426               //updating its properties
   427               mapwin.updateEdge(active_edge);
   428             }
   429             else
   430             {
   431               target_node=INVALID;
   432               std::cerr << "Loop edge is not yet implemented!" << std::endl;
   433             }
   434           }
   435           //clicked item was not a node. it could be an e.g. edge. we do not
   436           //deal with it furthermore.
   437           else
   438           {
   439             target_item=NULL;
   440           }
   441         }
   442       }
   443       break;
   444     case GDK_BUTTON_RELEASE:
   445       isbutton=0;
   446       //we clear settings in two cases
   447       //1: the edge is ready (target_item has valid value)
   448       //2: the edge creation is cancelled with right button
   449       if((target_item)||(e->button.button==3))
   450       {
   451         if(active_item)
   452         {
   453           *active_item << Gnome::Canvas::Properties::fill_color("blue");
   454           active_item=NULL;
   455         }
   456         if(target_item)
   457         {
   458           *target_item << Gnome::Canvas::Properties::fill_color("blue");
   459           target_item=NULL;
   460         }
   461         active_node=INVALID;
   462         active_edge=INVALID;
   463       }
   464       break;
   465     default:
   466       break;
   467   }
   468   return false;
   469 }
   470 
   471 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
   472 {
   473   switch(e->type)
   474     {
   475     case GDK_BUTTON_PRESS:
   476       //finding the clicked items
   477       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   478       active_item=(get_item_at(clicked_x, clicked_y));
   479       active_node=INVALID;
   480       active_edge=INVALID;
   481       //was it a node?
   482       for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   483 	{
   484 	  if(nodesmap[i]==active_item)
   485 	    {
   486 	      active_node=i;
   487 	    }
   488 	}
   489       //or was it an edge?
   490       if(active_node==INVALID)
   491 	{
   492 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   493 	    {
   494 	      if(edgesmap[i]==active_item)
   495 		{
   496 		  active_edge=i;
   497 		}
   498 	    }
   499 	}
   500 
   501       //recolor activated item
   502       if(active_item)
   503 	{
   504 	  *active_item << Gnome::Canvas::Properties::fill_color("red");
   505 	}
   506       break;
   507 
   508     case GDK_BUTTON_RELEASE:
   509       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   510       if(active_item)
   511 	{
   512 	  //the cursor was not moved since pressing it
   513 	  if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
   514 	    {
   515 	      //a node was found
   516 	      if(active_node!=INVALID)
   517 		{
   518                   mapstorage.modified = true;
   519 
   520 		  std::set<Graph::Edge> edges_to_delete;
   521 
   522 		  for(OutEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
   523 		    {
   524 		      edges_to_delete.insert(e);
   525 		    }
   526 		  
   527 		  for(InEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
   528 		    {
   529 		      edges_to_delete.insert(e);
   530 		    }
   531 		  
   532 		  //deleting collected edges
   533 		  for(std::set<Graph::Edge>::iterator
   534 			edge_set_it=edges_to_delete.begin();
   535 		      edge_set_it!=edges_to_delete.end();
   536 		      ++edge_set_it)
   537 		    {
   538 		      deleteItem(*edge_set_it);
   539 		    }
   540 		  deleteItem(active_node);
   541 		}
   542 	      //a simple edge was chosen
   543 	      else
   544 		{
   545 		  deleteItem(active_edge);
   546 		}
   547 	    }
   548 	  //pointer was moved, deletion is cancelled
   549 	  else
   550 	    {
   551 	      if(active_node!=INVALID)
   552 		{
   553 		  *active_item << Gnome::Canvas::Properties::fill_color("blue");
   554 		}
   555 	      else
   556 		{
   557 		  *active_item << Gnome::Canvas::Properties::fill_color("green");
   558 		}
   559 	    }
   560 	}
   561       //reseting datas
   562       active_item=NULL;
   563       active_edge=INVALID;
   564       active_node=INVALID;
   565       break;
   566 
   567     case GDK_MOTION_NOTIFY:
   568       break;
   569 
   570     default:
   571       break;
   572     }
   573   return false;
   574 }
   575 
   576 bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
   577 {
   578   if(actual_tool==EDGE_MAP_EDIT)
   579   {
   580     switch(e->type)
   581     {
   582       case GDK_BUTTON_PRESS:
   583         {
   584           //for determine, whether it was an edge
   585           Edge clicked_edge=INVALID;
   586 
   587           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   588           active_item=(get_item_at(clicked_x, clicked_y));
   589 
   590           //find the activated item between texts
   591           for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   592           {
   593             //at the same time only one can be active
   594             if(edgetextmap[i]==active_item)
   595             {
   596               clicked_edge=i;
   597             }
   598           }
   599 
   600           //if it was not between texts, search for it between edges
   601           if(clicked_edge==INVALID)
   602           {
   603             for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   604             {
   605               //at the same time only one can be active
   606               if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
   607               {
   608                 clicked_edge=i;
   609               }
   610             }
   611           }
   612  
   613           //if it was really an edge...
   614           if(clicked_edge!=INVALID)
   615           {
   616             // the id map is not editable
   617             if (edgemap_to_edit == "id") return 0;
   618 
   619             //and there is activated map
   620             if(edgetextmap[clicked_edge]->property_text().get_value()!="")
   621             {
   622               //activate the general variable for it
   623               active_edge=clicked_edge;
   624 
   625               //create a dialog
   626               Gtk::Dialog dialog("Edit value", *parentwin, true);
   627               dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   628               dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   629               Gtk::VBox* vbox = dialog.get_vbox();
   630               Gtk::Adjustment adj(
   631                   (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge],
   632                   -1000000.0,
   633                   1000000.0,
   634                   1.0, 5.0, 0.0);
   635               //TODO: find out why doesn't it work with
   636               //numeric_limits<double>::min/max
   637               Gtk::SpinButton spin(adj);
   638               spin.set_numeric(true);
   639               spin.set_digits(4);
   640               vbox->add(spin);
   641               spin.show();
   642               switch (dialog.run())
   643               {
   644                 case Gtk::RESPONSE_NONE:
   645                 case Gtk::RESPONSE_CANCEL:
   646                   break;
   647                 case Gtk::RESPONSE_ACCEPT:
   648                   double new_value = spin.get_value();
   649                   (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge] =
   650                     new_value;
   651                   std::ostringstream ostr;
   652                   ostr << new_value;
   653                   edgetextmap[active_edge]->property_text().set_value(
   654                       ostr.str());
   655                   //mapwin.updateEdge(active_edge);
   656                   mapwin.updateEdge(Edge(INVALID));
   657               }
   658             }
   659           }
   660           break;
   661         }
   662       default:
   663         break;
   664     }
   665   }
   666   return false;  
   667 }
   668 
   669 bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
   670 {
   671   if(actual_tool==NODE_MAP_EDIT)
   672   {
   673     switch(e->type)
   674     {
   675       case GDK_BUTTON_PRESS:
   676         {
   677           //for determine, whether it was a node
   678           Node clicked_node=INVALID;
   679 
   680           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   681           active_item=(get_item_at(clicked_x, clicked_y));
   682 
   683           //find the activated item between texts
   684           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   685           {
   686             //at the same time only one can be active
   687             if(nodetextmap[i]==active_item)
   688             {
   689               clicked_node=i;
   690             }
   691           }
   692 
   693           //if there was not, search for it between nodes
   694           if(clicked_node==INVALID)
   695           {
   696             for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   697             {
   698               //at the same time only one can be active
   699               if(nodesmap[i]==active_item)
   700               {
   701                 clicked_node=i;
   702               }
   703             }
   704           }
   705 
   706           //if it was really a node...
   707           if(clicked_node!=INVALID)
   708           {
   709             // the id map is not editable
   710             if (nodemap_to_edit == "id") return 0;
   711 
   712             //and there is activated map
   713             if(nodetextmap[clicked_node]->property_text().get_value()!="")
   714             {
   715               //activate the general variable for it
   716               active_node=clicked_node;
   717 
   718               //create a dialog
   719               Gtk::Dialog dialog("Edit value", *parentwin, true);
   720               dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   721               dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   722               Gtk::VBox* vbox = dialog.get_vbox();
   723               Gtk::Adjustment adj(
   724                   (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node],
   725                   -1000000.0,
   726                   1000000.0,
   727                   1.0, 5.0, 0.0);
   728               //TODO: find out why doesn't it work with
   729               //numeric_limits<double>::min/max
   730               Gtk::SpinButton spin(adj);
   731               spin.set_numeric(true);
   732               spin.set_digits(4);
   733               vbox->add(spin);
   734               spin.show();
   735               switch (dialog.run())
   736               {
   737                 case Gtk::RESPONSE_NONE:
   738                 case Gtk::RESPONSE_CANCEL:
   739                   break;
   740                 case Gtk::RESPONSE_ACCEPT:
   741                   double new_value = spin.get_value();
   742                   (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node] =
   743                     new_value;
   744                   std::ostringstream ostr;
   745                   ostr << new_value;
   746                   nodetextmap[active_node]->property_text().set_value(
   747                       ostr.str());
   748                   //mapwin.updateNode(active_node);
   749                   mapwin.updateNode(Node(INVALID));
   750               }
   751             }
   752           }
   753           break;
   754         }
   755       default:
   756         break;
   757     }
   758   }
   759   return false;  
   760 }
   761 
   762 void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
   763 {
   764   delete(nodetextmap[node_to_delete]);
   765   delete(nodesmap[node_to_delete]);
   766   mapstorage.graph.erase(node_to_delete);
   767 }
   768 
   769 void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
   770 {
   771   delete(edgetextmap[edge_to_delete]);
   772   delete(edgesmap[edge_to_delete]);
   773   mapstorage.graph.erase(edge_to_delete);
   774 }
   775 
   776 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
   777 {
   778   new_place+=(xy<double>(10,10));
   779   edgetextmap[forming_edge]->property_x().set_value(new_place.x);
   780   edgetextmap[forming_edge]->property_y().set_value(new_place.y);
   781 }
   782 
   783 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
   784 {
   785   if(on)
   786     {
   787       if(forming_edge!=INVALID)
   788 	{
   789 	  std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
   790 	}
   791       else
   792 	{
   793 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   794 	    {
   795 	      if(edgesmap[i]==active_bre)
   796 		{
   797 		  forming_edge=i;
   798 		}
   799 	    }
   800 	}
   801     }
   802   else
   803     {
   804       if(forming_edge!=INVALID)
   805 	{
   806 	  forming_edge=INVALID;
   807 	}
   808       else
   809 	{
   810 	  std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
   811 	}
   812     }
   813 
   814 }
   815 
   816 int GraphDisplayerCanvas::addNewEdgeMap(double default_value, std::string mapname)
   817 {
   818   //create the new map
   819   Graph::EdgeMap<double> * emptr=new Graph::EdgeMap<double> (mapstorage.graph, default_value);
   820 
   821   //if addition was not successful addEdgeMap returns one.
   822   //cause can be that there is already a map named like the new one
   823   if(mapstorage.addEdgeMap(mapname,emptr, default_value))
   824     {
   825       return 1;
   826     }
   827 
   828 
   829   //add it to the list of the displayable maps
   830   mapwin.registerNewEdgeMap(mapname);
   831 
   832   //display it
   833   changeEdgeText(mapname);
   834 
   835   return 0;
   836 }
   837 
   838 int GraphDisplayerCanvas::addNewNodeMap(double default_value, std::string mapname)
   839 {
   840   //create the new map
   841   Graph::NodeMap<double> * emptr=new Graph::NodeMap<double> (mapstorage.graph,default_value);
   842 
   843   //if addition was not successful addNodeMap returns one.
   844   //cause can be that there is already a map named like the new one
   845   if(mapstorage.addNodeMap(mapname,emptr, default_value))
   846     {
   847       return 1;
   848     }
   849 
   850   //add it to the list of the displayable maps
   851   mapwin.registerNewNodeMap(mapname);
   852 
   853   //display it
   854   changeNodeText(mapname);
   855 
   856   return 0;
   857 }
   858