graph_displayer_canvas-event.cc
author ladanyi
Tue, 23 Aug 2005 07:36:09 +0000
branchgui
changeset 63 59768817442a
parent 62 80eefca04b1e
child 64 7a32d528857f
permissions -rwxr-xr-x
- id maps are not editable
- handle exceptions thrown by the file reader
- texts are always above the edges
- store a default value for all maps, so that edges and nodes created after
adding a new map receive the default value too
- create node on button release, not on click (fixes a few oddities)
     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 	    GdkEvent * generated=new GdkEvent();
    36 	    generated->type=GDK_KEY_PRESS;
    37 	    ((GdkEventKey*)generated)->keyval=GDK_KP_Enter;
    38 	    entryWidgetChangeHandler(generated);
    39 	    entrywidget.hide();
    40 	    break;
    41 	  }
    42 	default:
    43 	  break;
    44 	}
    45 
    46       active_item=NULL; 
    47       target_item=NULL; 
    48       active_edge=INVALID;	
    49       active_node=INVALID;	
    50 
    51 
    52       actual_tool=newtool;
    53   
    54       switch(newtool)
    55 	{
    56 	case MOVE:
    57 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
    58 	  break;
    59 
    60 	case CREATE_NODE:
    61 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
    62 	  break;
    63 
    64 	case CREATE_EDGE:
    65 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
    66 	  break;
    67 
    68 	case ERASER:
    69 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
    70 	  break;
    71 
    72 	case EDGE_MAP_EDIT:
    73 	  grab_focus();
    74 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
    75 	  break;
    76 
    77 	case NODE_MAP_EDIT:
    78 	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
    79 	  break;
    80 
    81 	default:
    82 	  break;
    83 	}
    84     }
    85 }
    86 
    87 int GraphDisplayerCanvas::getActualTool()
    88 {
    89   return actual_tool;
    90 }
    91 
    92 bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
    93 {
    94   switch(e->type)
    95   {
    96     case GDK_BUTTON_PRESS:
    97       //we mark the location of the event to be able to calculate parameters of dragging
    98       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
    99 
   100       active_item=(get_item_at(clicked_x, clicked_y));
   101       active_node=INVALID;
   102       for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   103 	{
   104 	  if(nodesmap[i]==active_item)
   105 	    {
   106 	      active_node=i;
   107 	    }
   108 	}
   109       switch(e->button.button)
   110 	{
   111 	case 3:      
   112 	  isbutton=3;
   113 	  break;
   114 	default:
   115 	  isbutton=1;
   116 	  break;
   117 	}
   118       break;
   119     case GDK_BUTTON_RELEASE:
   120       isbutton=0;
   121       active_item=NULL;
   122       active_node=INVALID;
   123       break;
   124     case GDK_MOTION_NOTIFY:
   125       //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
   126       if(active_node!=INVALID)
   127       {
   128         mapstorage.modified = true;
   129         mapstorage.coords.set(active_node, xy<double>(clicked_x, clicked_y));
   130 	//new coordinates will be the old values,
   131 	//because the item will be moved to the
   132 	//new coordinate therefore the new movement
   133 	//has to be calculated from here
   134 
   135 	double new_x, new_y;
   136 
   137 	window_to_world (e->motion.x, e->motion.y, new_x, new_y);
   138 
   139         double dx=new_x-clicked_x;
   140         double dy=new_y-clicked_y;
   141 
   142 	//repositioning node and its text
   143         active_item->move(dx, dy);
   144 	nodetextmap[active_node]->move(dx, dy);
   145 
   146         clicked_x=new_x;
   147         clicked_y=new_y;
   148 
   149 	//all the edges connected to the moved point has to be redrawn
   150         EdgeIt ei;
   151 
   152         mapstorage.graph.firstOut(ei,active_node);
   153 
   154         for(;ei!=INVALID;mapstorage.graph.nextOut(ei))
   155         {
   156             Gnome::Canvas::Points coos;
   157             double x1, x2, y1, y2;
   158 
   159             nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
   160             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   161 
   162             nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
   163             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   164 
   165 	    if(isbutton==3)
   166 	      {
   167 		edgesmap[ei]->setPoints(coos);
   168 	      }
   169 	    else
   170 	      {
   171 		edgesmap[ei]->setPoints(coos,true);
   172 	      }
   173 
   174 	    //reposition of edgetext
   175 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   176 	    text_pos+=(xy<double>(10,10));
   177 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   178 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   179         }
   180 
   181         mapstorage.graph.firstIn(ei,active_node);
   182         for(;ei!=INVALID;mapstorage.graph.nextIn(ei))
   183         {
   184             Gnome::Canvas::Points coos;
   185             double x1, x2, y1, y2;
   186 
   187             nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
   188             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   189 
   190             nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
   191             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   192 
   193 	    if(isbutton==3)
   194 	      {
   195 		edgesmap[ei]->setPoints(coos);
   196 	      }
   197 	    else
   198 	      {
   199 		edgesmap[ei]->setPoints(coos,true);
   200 	      }
   201 
   202 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   203 	    text_pos+=(xy<double>(10,10));
   204 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   205 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   206         }
   207       }
   208     default: break;
   209   }
   210 
   211   return false;
   212 }
   213 
   214 bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
   215 {
   216   switch(e->type)
   217   {
   218     //move the new node
   219     case GDK_MOTION_NOTIFY:
   220       {
   221         GdkEvent * generated=new GdkEvent();
   222         generated->motion.x=e->motion.x;
   223         generated->motion.y=e->motion.y;
   224         generated->type=GDK_MOTION_NOTIFY;
   225         moveEventHandler(generated);      
   226         break;
   227       }
   228 
   229     case GDK_BUTTON_RELEASE:
   230       mapstorage.modified = true;
   231 
   232       isbutton=1;
   233 
   234       active_node=mapstorage.graph.addNode();
   235 
   236       //initiating values corresponding to new node in maps
   237 
   238       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   239 
   240       // update coordinates
   241       mapstorage.coords.set(active_node, xy<double>(clicked_x, clicked_y));
   242 
   243       // update id map
   244       (*mapstorage.nodemap_storage["id"])[active_node] =
   245         mapstorage.graph.id(active_node);
   246 
   247       // update all other maps
   248       for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
   249           mapstorage.nodemap_storage.begin(); it !=
   250           mapstorage.nodemap_storage.end(); ++it)
   251       {
   252         if ((it->first != "id") &&
   253             (it->first != "coordinates_x") &&
   254             (it->first != "coordiantes_y"))
   255         {
   256           (*(it->second))[active_node] =
   257             mapstorage.nodemap_default[it->first];
   258         }
   259       }
   260 
   261       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph,
   262           clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   263       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   264       *(nodesmap[active_node]) <<
   265         Gnome::Canvas::Properties::fill_color("blue");
   266       *(nodesmap[active_node]) <<
   267         Gnome::Canvas::Properties::outline_color("black");
   268       active_item->raise_to_top();
   269 
   270       (nodesmap[active_node])->show();
   271 
   272       nodetextmap[active_node]=new Gnome::Canvas::Text(displayed_graph,
   273           clicked_x+node_property_defaults[N_RADIUS]+5,
   274           clicked_y+node_property_defaults[N_RADIUS]+5, "");
   275       nodetextmap[active_node]->property_fill_color().set_value("darkblue");
   276       nodetextmap[active_node]->raise_to_top();
   277 
   278       mapwin.updateNode(active_node);
   279 
   280       isbutton=0;
   281       target_item=NULL;
   282       active_item=NULL;
   283       active_node=INVALID;
   284 
   285       break;
   286     default:
   287       break;
   288   }
   289   return false;
   290 }
   291 
   292 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
   293 {
   294   switch(e->type)
   295   {
   296     case GDK_BUTTON_PRESS:
   297       //in edge creation right button has special meaning
   298       if(e->button.button!=3)
   299       {
   300         //there is not yet selected node
   301         if(active_node==INVALID)
   302         {
   303           //we mark the location of the event to be able to calculate parameters of dragging
   304 
   305           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   306 
   307           active_item=(get_item_at(clicked_x, clicked_y));
   308           active_node=INVALID;
   309           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   310           {
   311             if(nodesmap[i]==active_item)
   312             {
   313               active_node=i;
   314             }
   315           }
   316           //the clicked item is really a node
   317           if(active_node!=INVALID)
   318           {
   319             *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   320             isbutton=1;
   321           }
   322           //clicked item was not a node. It could be e.g. edge.
   323           else
   324           {
   325             active_item=NULL;
   326           }
   327         }
   328         //we only have to do sg. if the mouse button
   329         // is pressed already once AND the click was
   330         // on a node that was found in the set of 
   331         //nodes, and now we only search for the second 
   332         //node
   333         else
   334         {
   335           window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   336           target_item=(get_item_at(clicked_x, clicked_y));
   337           Node target_node=INVALID;
   338           for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   339           {
   340             if(nodesmap[i]==target_item)
   341             {
   342               target_node=i;
   343             }
   344           }
   345           //the clicked item is a node, the edge can be drawn
   346           if(target_node!=INVALID)
   347           {
   348             if(target_node!=active_node)		
   349             {
   350               mapstorage.modified = true;
   351 
   352               *(nodesmap[target_node]) <<
   353                 Gnome::Canvas::Properties::fill_color("red");
   354 
   355               //creating new edge
   356               active_edge=mapstorage.graph.addEdge(active_node,
   357                   target_node);
   358 
   359               // update id map
   360               (*mapstorage.edgemap_storage["id"])[active_edge] = 
   361                 mapstorage.graph.id(active_edge);
   362  
   363               // update all other maps
   364               for (std::map<std::string,
   365                   Graph::EdgeMap<double>*>::const_iterator it =
   366                   mapstorage.edgemap_storage.begin(); it !=
   367                   mapstorage.edgemap_storage.end(); ++it)
   368               {
   369                 if (it->first != "id")
   370                 {
   371                   (*(it->second))[active_edge] =
   372                     mapstorage.edgemap_default[it->first];
   373                 }
   374               }
   375 
   376               //calculating coordinates of new edge
   377               Gnome::Canvas::Points coos;
   378               double x1, x2, y1, y2;
   379 
   380               active_item->get_bounds(x1, y1, x2, y2);
   381               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   382 
   383               target_item->get_bounds(x1, y1, x2, y2);
   384               coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   385 
   386               //drawing new edge
   387               edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos,
   388                   *this);
   389               *(edgesmap[active_edge]) <<
   390                 Gnome::Canvas::Properties::fill_color("green");
   391               edgesmap[active_edge]->property_width_pixels().set_value(10);
   392 
   393               edgesmap[active_edge]->lower_to_bottom();
   394 
   395               //initializing edge-text as well, to empty string
   396               xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
   397               text_pos+=(xy<double>(10,10));
   398 
   399               edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
   400                   text_pos.x, text_pos.y, "");
   401               edgetextmap[active_edge]->property_fill_color().set_value(
   402                   "darkgreen");
   403               edgetextmap[active_edge]->raise_to_top();
   404 
   405               //updating its properties
   406               mapwin.updateEdge(active_edge);
   407             }
   408             else
   409             {
   410               target_node=INVALID;
   411               std::cerr << "Loop edge is not yet implemented!" << std::endl;
   412             }
   413           }
   414           //clicked item was not a node. it could be an e.g. edge. we do not
   415           //deal with it furthermore.
   416           else
   417           {
   418             target_item=NULL;
   419           }
   420         }
   421       }
   422       break;
   423     case GDK_BUTTON_RELEASE:
   424       isbutton=0;
   425       //we clear settings in two cases
   426       //1: the edge is ready (target_item has valid value)
   427       //2: the edge creation is cancelled with right button
   428       if((target_item)||(e->button.button==3))
   429       {
   430         if(active_item)
   431         {
   432           *active_item << Gnome::Canvas::Properties::fill_color("blue");
   433           active_item=NULL;
   434         }
   435         if(target_item)
   436         {
   437           *target_item << Gnome::Canvas::Properties::fill_color("blue");
   438           target_item=NULL;
   439         }
   440         active_node=INVALID;
   441         active_edge=INVALID;
   442       }
   443       break;
   444     default:
   445       break;
   446   }
   447   return false;
   448 }
   449 
   450 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
   451 {
   452   switch(e->type)
   453     {
   454     case GDK_BUTTON_PRESS:
   455       //finding the clicked items
   456       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   457       active_item=(get_item_at(clicked_x, clicked_y));
   458       active_node=INVALID;
   459       active_edge=INVALID;
   460       //was it a node?
   461       for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   462 	{
   463 	  if(nodesmap[i]==active_item)
   464 	    {
   465 	      active_node=i;
   466 	    }
   467 	}
   468       //or was it an edge?
   469       if(active_node==INVALID)
   470 	{
   471 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   472 	    {
   473 	      if(edgesmap[i]==active_item)
   474 		{
   475 		  active_edge=i;
   476 		}
   477 	    }
   478 	}
   479 
   480       //recolor activated item
   481       if(active_item)
   482 	{
   483 	  *active_item << Gnome::Canvas::Properties::fill_color("red");
   484 	}
   485       break;
   486 
   487     case GDK_BUTTON_RELEASE:
   488       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   489       if(active_item)
   490 	{
   491 	  //the cursor was not moved since pressing it
   492 	  if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
   493 	    {
   494 	      //a node was found
   495 	      if(active_node!=INVALID)
   496 		{
   497                   mapstorage.modified = true;
   498 
   499 		  //collecting edges to delete
   500 		  EdgeIt e;
   501 		  std::set<Graph::Edge> edges_to_delete;
   502 
   503 		  mapstorage.graph.firstOut(e,active_node);
   504 		  for(;e!=INVALID;mapstorage.graph.nextOut(e))
   505 		    {
   506 		      edges_to_delete.insert(e);
   507 		    }
   508 
   509 		  mapstorage.graph.firstIn(e,active_node);
   510 		  for(;e!=INVALID;mapstorage.graph.nextIn(e))
   511 		    {
   512 		      edges_to_delete.insert(e);
   513 		    }
   514 
   515 		  //deleting collected edges
   516 		  for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
   517 		    {
   518 		      deleteItem(*edge_set_it);
   519 		    }
   520 		  deleteItem(active_node);
   521 		}
   522 	      //a simple edge was chosen
   523 	      else
   524 		{
   525 		  deleteItem(active_edge);
   526 		}
   527 	    }
   528 	  //pointer was moved, deletion is cancelled
   529 	  else
   530 	    {
   531 	      if(active_node!=INVALID)
   532 		{
   533 		  *active_item << Gnome::Canvas::Properties::fill_color("blue");
   534 		}
   535 	      else
   536 		{
   537 		  *active_item << Gnome::Canvas::Properties::fill_color("green");
   538 		}
   539 	    }
   540 	}
   541       //reseting datas
   542       active_item=NULL;
   543       active_edge=INVALID;
   544       active_node=INVALID;
   545       break;
   546 
   547     case GDK_MOTION_NOTIFY:
   548       break;
   549 
   550     default:
   551       break;
   552     }
   553   return false;
   554 }
   555 
   556 bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
   557 {
   558   if(actual_tool==EDGE_MAP_EDIT)
   559     {
   560       switch(e->type)
   561 	{
   562 	case GDK_KEY_PRESS:
   563 	  //for Escape or Enter hide the displayed widget
   564 	  {
   565 	    nodeMapEditEventHandler(e);
   566 	    break;
   567 	  }
   568 	case GDK_BUTTON_PRESS:
   569 	  //If the click happened on an edge we place the entrywidget there and fill in the value of the activated map at that edge.
   570 	  {
   571 	    //for determine, whether it was an edge
   572 	    Edge clicked_edge=INVALID;
   573 
   574 	    //find the activated item between texts
   575 	    active_item=(get_item_at(e->button.x, e->button.y));
   576 	    for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   577 	      {
   578 		if(edgetextmap[i]==active_item)
   579 		  {
   580 		    clicked_edge=i;
   581 		  }
   582 	      }
   583 
   584 	    //if it was not between texts, search for it between edges
   585 	    if(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 		for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   591 		  {
   592 		    //at the same time only one can be active
   593 		    if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
   594 		      {
   595 			clicked_edge=i;
   596 		      }
   597 		  }
   598 	      }
   599 	    //if it was really an edge...
   600 	    if(clicked_edge!=INVALID)
   601 	      {
   602                 // the id map is not editable
   603                 if (nodemap_to_edit == "id") return 0;
   604 		//If there is already edited edge, it has to be saved first
   605 		if(entrywidget.is_visible())
   606 		  {
   607 		    GdkEvent * generated=new GdkEvent();
   608 		    generated->type=GDK_KEY_PRESS;
   609 		    ((GdkEventKey*)generated)->keyval=GDK_KP_Enter;
   610 		    entryWidgetChangeHandler(generated);
   611 		  }
   612 		//If the previous value could be saved, we can go further, otherwise not
   613 		if(!entrywidget.is_visible())
   614 		  {
   615 		    //and there is activated map
   616 		    if(edgetextmap[clicked_edge]->property_text().get_value()!="")
   617 		      {
   618 			//activate the general variable for it
   619 			active_edge=clicked_edge;
   620 			//delete visible widget if there is
   621 			if(canvasentrywidget)
   622 			  {
   623 			    delete(canvasentrywidget);
   624 			  }
   625 
   626 			//initialize the entry
   627 			entrywidget.show();
   628 
   629 			//fill in the correct value
   630 			entrywidget.set_text(edgetextmap[active_edge]->property_text().get_value());
   631 
   632 			//replace and resize the entry to the activated edge and put it in a Canvas::Widget to be able to display it on gdc
   633 			xy<double> entry_coos;
   634 			entry_coos.x=(edgetextmap[active_edge])->property_x().get_value();
   635 			entry_coos.x-=edgetextmap[active_edge]->property_text_width().get_value()/2;
   636 			entry_coos.y=(edgetextmap[active_edge])->property_y().get_value();
   637 			entry_coos.y-=edgetextmap[active_edge]->property_text_height().get_value()*1.5/2;
   638 			canvasentrywidget=new Gnome::Canvas::Widget(displayed_graph, entry_coos.x, entry_coos.y, entrywidget);
   639 			canvasentrywidget->property_width().set_value(edgetextmap[active_edge]->property_text_width().get_value()*4);
   640 			canvasentrywidget->property_height().set_value(edgetextmap[active_edge]->property_text_height().get_value()*1.5);
   641 
   642 			//setting the focus to newly created widget
   643 			parentwin->set_focus(entrywidget);
   644 			parentwin->activate_focus();
   645 		      }
   646 		  }
   647 	      }
   648 	    //if it was not an edge...
   649 	    else
   650 	      {
   651 		//In this case the click did not happen on an edge
   652 		//if there is visible entry we save the value in it
   653 		//we pretend like an Enter was presse din the Entry widget
   654 		GdkEvent * generated=new GdkEvent();
   655 		generated->type=GDK_KEY_PRESS;
   656 		((GdkEventKey*)generated)->keyval=GDK_KP_Enter;
   657 		entryWidgetChangeHandler(generated);
   658 	      }
   659 	    break;
   660 	  }
   661 	default:
   662 	  break;
   663 	}
   664     }
   665   return false;  
   666 }
   667 
   668 bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
   669 {
   670   if(actual_tool==NODE_MAP_EDIT)
   671     {
   672       switch(e->type)
   673 	{
   674 	case GDK_KEY_PRESS:
   675 	  //for Escape or Enter hide the displayed widget
   676 	  {
   677 	    switch(((GdkEventKey*)e)->keyval)
   678 	      {
   679 	      case GDK_Escape:
   680 		entrywidget.hide();
   681 		break;
   682 	      case GDK_Return:
   683 	      case GDK_KP_Enter:
   684 		entrywidget.hide();
   685 		break;
   686 	      default:
   687 		break;
   688 	      }
   689   
   690 	    break;
   691 	  }
   692 	case GDK_BUTTON_PRESS:
   693 	  //If the click happened on an edge we place the entrywidget there and fill in the value of the activated map at that edge.
   694 	  {
   695 	    //for determine, whether it was a node
   696 	    Node clicked_node=INVALID;
   697 
   698 	    //find the activated item between texts
   699 	    active_item=(get_item_at(e->button.x, e->button.y));
   700 	    for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   701 	      {
   702 		//at the same time only one can be active
   703 		if(nodetextmap[i]==active_item)
   704 		  {
   705 		    clicked_node=i;
   706 		  }
   707 	      }
   708 
   709 	    //if there was not, search for it between nodes
   710 	    if(clicked_node==INVALID)
   711 	      {
   712 		window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   713 		active_item=(get_item_at(clicked_x, clicked_y));
   714 
   715 		for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
   716 		  {
   717 		    //at the same time only one can be active
   718 		    if(nodesmap[i]==active_item)
   719 		      {
   720 			clicked_node=i;
   721 		      }
   722 		  }
   723 	      }
   724 	    //if it was really an edge...
   725 	    if(clicked_node!=INVALID)
   726 	      {
   727                 // the id map is not editable
   728                 if (nodemap_to_edit == "id") return 0;
   729 		//If there is already edited edge, it has to be saved first
   730 		if(entrywidget.is_visible())
   731 		  {
   732 		    GdkEvent * generated=new GdkEvent();
   733 		    generated->type=GDK_KEY_PRESS;
   734 		    ((GdkEventKey*)generated)->keyval=GDK_KP_Enter;
   735 		    entryWidgetChangeHandler(generated);
   736 		  }
   737 		//If the previous value could be saved, we can go further, otherwise not
   738 		if(!entrywidget.is_visible())
   739 		  {
   740 		    //and there is activated map
   741 		    if(nodetextmap[clicked_node]->property_text().get_value()!="")
   742 		      {
   743 			//activate the general variable for it
   744 			active_node=clicked_node;
   745 			//delete visible widget if there is
   746 			if(canvasentrywidget)
   747 			  {
   748 			    delete(canvasentrywidget);
   749 			  }
   750 
   751 			//initialize the entry
   752 			entrywidget.show();
   753 
   754 			//fill in the correct value
   755 			entrywidget.set_text(nodetextmap[active_node]->property_text().get_value());
   756 
   757 			//replace and resize the entry to the activated node and put it in a Canvas::Widget to be able to display it on gdc
   758 			xy<double> entry_coos;
   759 			entry_coos.x=(nodetextmap[active_node])->property_x().get_value();
   760 			entry_coos.x-=nodetextmap[active_node]->property_text_width().get_value()/2;
   761 			entry_coos.y=(nodetextmap[active_node])->property_y().get_value();
   762 			entry_coos.y-=nodetextmap[active_node]->property_text_height().get_value()*1.5/2;
   763 			canvasentrywidget=new Gnome::Canvas::Widget(displayed_graph, entry_coos.x, entry_coos.y, entrywidget);
   764 			canvasentrywidget->property_width().set_value(nodetextmap[active_node]->property_text_width().get_value()*4);
   765 			canvasentrywidget->property_height().set_value(nodetextmap[active_node]->property_text_height().get_value()*1.5);
   766 		      }
   767 		  }
   768 	      }
   769 	    //if it was not an edge...
   770 	    else
   771 	      {
   772 		//In this case the click did not happen on an edge
   773 		//if there is visible entry we save the value in it
   774 		//we pretend like an Enter was presse din the Entry widget
   775 		GdkEvent * generated=new GdkEvent();
   776 		generated->type=GDK_KEY_PRESS;
   777 		((GdkEventKey*)generated)->keyval=GDK_KP_Enter;
   778 		entryWidgetChangeHandler(generated);
   779 	      }
   780 	    break;
   781 	  }
   782 	default:
   783 	  break;
   784 	}
   785     }
   786   return false;  
   787 }
   788 
   789 bool GraphDisplayerCanvas::entryWidgetChangeHandler(GdkEvent* e)
   790 {
   791   if(entrywidget.is_visible())
   792     {
   793       if(e->type==GDK_KEY_PRESS)
   794 	{
   795 	  switch(((GdkEventKey*)e)->keyval)
   796 	    {
   797 	    case GDK_Escape:
   798 	      entrywidget.hide();
   799 	      break;
   800 	    case GDK_KP_Enter:
   801 	    case GDK_Return:
   802 	      {
   803 		//these variables check whether the text in the entry is valid
   804 		bool valid_double=true;
   805 		int point_num=0;
   806 
   807 		//getting the value from the entry and converting it to double
   808 		Glib::ustring mapvalue_str = entrywidget.get_text();
   809 
   810 		char * mapvalue_ch=new char [mapvalue_str.length()];
   811 		for(int i=0;i<(int)(mapvalue_str.length());i++)
   812 		  {
   813 		    if(((mapvalue_str[i]<'0')||(mapvalue_str[i]>'9'))&&(mapvalue_str[i]!='.'))
   814 		      {
   815 			valid_double=false;
   816 		      }
   817 		    else
   818 		      {
   819 			if(mapvalue_str[i]=='.')
   820 			  {
   821 			    point_num++;
   822 			  }
   823 		      }
   824 		    mapvalue_ch[i]=mapvalue_str[i];
   825 		  }
   826   	      
   827 		//if the text in the entry was correct
   828 		if((point_num<=1)&&(valid_double))
   829 		  {
   830 		    double mapvalue_d=atof(mapvalue_ch);
   831 
   832 		    //reconvert the double to string for the correct format
   833 		    std::ostringstream ostr;
   834 		    ostr << mapvalue_d;
   835 
   836 		    //save the value to the correct place
   837 		    switch(actual_tool)
   838 		      {
   839 		      case EDGE_MAP_EDIT:
   840 			edgetextmap[active_edge]->property_text().set_value(ostr.str());
   841 			(*(mapstorage.edgemap_storage)[edgemap_to_edit])[active_edge]=mapvalue_d;
   842 			mapwin.updateEdge(active_edge);
   843 			break;
   844 		      case NODE_MAP_EDIT:
   845 			nodetextmap[active_node]->property_text().set_value(ostr.str());
   846 			(*(mapstorage.nodemap_storage)[nodemap_to_edit])[active_node]=mapvalue_d;
   847 			mapwin.updateNode(active_node);
   848 			break;
   849 		      default:
   850 			break;
   851 		      }
   852 		    entrywidget.hide();
   853 		  }
   854 		//the text in the entry was not correct for a double
   855 		else
   856 		  {
   857 		    std::cerr << "ERROR: only handling of double values is implemented yet!" << std::endl;
   858 		  }
   859 
   860 		break;
   861 	      }
   862 	    default:
   863 	      break;
   864 	    }
   865 	}
   866     }
   867   return false;
   868 }
   869 
   870 void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
   871 {
   872   delete(nodetextmap[node_to_delete]);
   873   delete(nodesmap[node_to_delete]);
   874   mapstorage.graph.erase(node_to_delete);
   875 }
   876 
   877 void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
   878 {
   879   delete(edgetextmap[edge_to_delete]);
   880   delete(edgesmap[edge_to_delete]);
   881   mapstorage.graph.erase(edge_to_delete);
   882 }
   883 
   884 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
   885 {
   886   new_place+=(xy<double>(10,10));
   887   edgetextmap[forming_edge]->property_x().set_value(new_place.x);
   888   edgetextmap[forming_edge]->property_y().set_value(new_place.y);
   889 }
   890 
   891 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
   892 {
   893   if(on)
   894     {
   895       if(forming_edge!=INVALID)
   896 	{
   897 	  std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
   898 	}
   899       else
   900 	{
   901 	  for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
   902 	    {
   903 	      if(edgesmap[i]==active_bre)
   904 		{
   905 		  forming_edge=i;
   906 		}
   907 	    }
   908 	}
   909     }
   910   else
   911     {
   912       if(forming_edge!=INVALID)
   913 	{
   914 	  forming_edge=INVALID;
   915 	}
   916       else
   917 	{
   918 	  std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
   919 	}
   920     }
   921 
   922 }
   923 
   924 int GraphDisplayerCanvas::addNewEdgeMap(double default_value, std::string mapname)
   925 {
   926   //create the new map
   927   Graph::EdgeMap<double> * emptr=new Graph::EdgeMap<double> (mapstorage.graph, default_value);
   928 
   929   //if addition was not successful addEdgeMap returns one.
   930   //cause can be that there is already a map named like the new one
   931   if(mapstorage.addEdgeMap(mapname,emptr, default_value))
   932     {
   933       return 1;
   934     }
   935 
   936 
   937   //add it to the list of the displayable maps
   938   mapwin.registerNewEdgeMap(mapname);
   939 
   940   //display it
   941   changeEdgeText(mapname);
   942 
   943   return 0;
   944 }
   945 
   946 int GraphDisplayerCanvas::addNewNodeMap(double default_value, std::string mapname)
   947 {
   948   //create the new map
   949   Graph::NodeMap<double> * emptr=new Graph::NodeMap<double> (mapstorage.graph,default_value);
   950 
   951   //if addition was not successful addNodeMap returns one.
   952   //cause can be that there is already a map named like the new one
   953   if(mapstorage.addNodeMap(mapname,emptr, default_value))
   954     {
   955       return 1;
   956     }
   957 
   958   //add it to the list of the displayable maps
   959   mapwin.registerNewNodeMap(mapname);
   960 
   961   //display it
   962   changeNodeText(mapname);
   963 
   964   return 0;
   965 }
   966