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