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