gui/graph_displayer_canvas-event.cc
author hegyi
Tue, 12 Jul 2005 18:21:49 +0000
changeset 1550 4dcbb4ab1d7a
parent 1525 6d94de269ab1
child 1551 2b45f64f6377
permissions -rwxr-xr-x
Editors are based.
     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   actual_handler.disconnect();
    17 
    18   if(actual_tool==CREATE_EDGE)
    19     {
    20 	GdkEvent * generated=new GdkEvent();
    21 	generated->type=GDK_BUTTON_RELEASE;
    22 	generated->button.button=3;
    23 	createEdgeEventHandler(generated);      
    24     }
    25 
    26   actual_tool=newtool;
    27 
    28   switch(newtool)
    29     {
    30     case MOVE:
    31       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
    32       break;
    33 
    34     case CREATE_NODE:
    35       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
    36       break;
    37 
    38     case CREATE_EDGE:
    39       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
    40       break;
    41 
    42     case ERASER:
    43       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
    44       break;
    45 
    46     case EDGE_MAP_EDIT:
    47       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
    48       break;
    49 
    50     case NODE_MAP_EDIT:
    51       actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
    52       break;
    53 
    54     default:
    55       break;
    56     }
    57 }
    58 
    59 int GraphDisplayerCanvas::getActualTool()
    60 {
    61   return actual_tool;
    62 }
    63 
    64 bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
    65 {
    66   switch(e->type)
    67   {
    68     case GDK_BUTTON_PRESS:
    69       //we mark the location of the event to be able to calculate parameters of dragging
    70       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
    71 
    72       active_item=(get_item_at(clicked_x, clicked_y));
    73       active_node=INVALID;
    74       for (NodeIt i(g); i!=INVALID; ++i)
    75 	{
    76 	  if(nodesmap[i]==active_item)
    77 	    {
    78 	      active_node=i;
    79 	    }
    80 	}
    81       switch(e->button.button)
    82 	{
    83 	case 3:      
    84 	  isbutton=3;
    85 	  break;
    86 	default:
    87 	  isbutton=1;
    88 	  break;
    89 	}
    90       break;
    91     case GDK_BUTTON_RELEASE:
    92       isbutton=0;
    93       active_item=NULL;
    94       active_node=INVALID;
    95       break;
    96     case GDK_MOTION_NOTIFY:
    97       //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
    98       if(active_node!=INVALID)
    99       {
   100 	//new coordinates will be the old values,
   101 	//because the item will be moved to the
   102 	//new coordinate therefore the new movement
   103 	//has to be calculated from here
   104 
   105 	double new_x, new_y;
   106 
   107 	window_to_world (e->motion.x, e->motion.y, new_x, new_y);
   108 
   109         double dx=new_x-clicked_x;
   110         double dy=new_y-clicked_y;
   111 
   112 	//repositioning node and its text
   113         active_item->move(dx, dy);
   114 	nodetextmap[active_node]->move(dx, dy);
   115 
   116         clicked_x=new_x;
   117         clicked_y=new_y;
   118 
   119 	//all the edges connected to the moved point has to be redrawn
   120         EdgeIt ei;
   121 
   122         g.firstOut(ei,active_node);
   123 
   124         for(;ei!=INVALID;g.nextOut(ei))
   125         {
   126             Gnome::Canvas::Points coos;
   127             double x1, x2, y1, y2;
   128 
   129             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   130             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   131 
   132             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   133             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   134 
   135 	    if(isbutton==3)
   136 	      {
   137 		edgesmap[ei]->setPoints(coos);
   138 	      }
   139 	    else
   140 	      {
   141 		edgesmap[ei]->setPoints(coos,true);
   142 	      }
   143 
   144 	    //reposition of edgetext
   145 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   146 	    text_pos+=(xy<double>(10,10));
   147 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   148 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   149         }
   150 
   151         g.firstIn(ei,active_node);
   152         for(;ei!=INVALID;g.nextIn(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 	    xy<double> text_pos=edgesmap[ei]->getArrowPos();
   173 	    text_pos+=(xy<double>(10,10));
   174 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   175 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   176         }
   177       }
   178     default: break;
   179   }
   180 
   181   return false;
   182 }
   183 
   184 bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
   185 {
   186   switch(e->type)
   187     {
   188 
   189       //draw the new node in red at the clicked place
   190     case GDK_2BUTTON_PRESS:
   191       std::cout << "double click" << std::endl;
   192       break;
   193     case GDK_BUTTON_PRESS:
   194       isbutton=1;
   195 
   196       active_node=NodeIt(g,g.addNode());
   197 
   198       //initiating values corresponding to new node in maps
   199 
   200       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   201 
   202       target_item=NULL;
   203       target_item=get_item_at(clicked_x, clicked_y);
   204 
   205       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   206       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   207       *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   208       *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
   209       (nodesmap[active_node])->show();
   210 
   211       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, "");
   212       nodetextmap[active_node]->property_fill_color().set_value("darkblue");
   213 
   214       mapwin->updateNode(active_node);
   215 
   216       break;
   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       //finalize the new node
   230     case GDK_BUTTON_RELEASE:
   231       isbutton=0;
   232       if(!target_item)
   233 	{
   234 	  //Its appropriate color is given by update.
   235 	  //*active_item << Gnome::Canvas::Properties::fill_color("blue");
   236 	}
   237       else
   238 	{
   239 	  //In this case the given color has to be overwritten, because the noe covers an other item.
   240 	  *active_item << Gnome::Canvas::Properties::fill_color("lightblue");
   241 	}
   242       target_item=NULL;
   243       active_item=NULL;
   244       active_node=INVALID;
   245       break;
   246     default:
   247       break;
   248     }
   249   return false;
   250 }
   251 
   252 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
   253 {
   254   switch(e->type)
   255     {
   256     case GDK_BUTTON_PRESS:
   257       //in edge creation right button has special meaning
   258       if(e->button.button!=3)
   259 	{
   260 	  //there is not yet selected node
   261 	  if(active_node==INVALID)
   262 	    {
   263 	      //we mark the location of the event to be able to calculate parameters of dragging
   264 
   265 	      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   266 
   267 	      active_item=(get_item_at(clicked_x, clicked_y));
   268 	      active_node=INVALID;
   269 	      for (NodeIt i(g); i!=INVALID; ++i)
   270 		{
   271 		  if(nodesmap[i]==active_item)
   272 		    {
   273 		      active_node=i;
   274 		    }
   275 		}
   276 	      //the clicked item is really a node
   277 	      if(active_node!=INVALID)
   278 		{
   279 		  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   280 		  isbutton=1;
   281 		}
   282 	      //clicked item was not a node. It could be e.g. edge.
   283 	      else
   284 		{
   285 		  active_item=NULL;
   286 		}
   287 	    }
   288 	  //we only have to do sg. if the mouse button
   289 	  // is pressed already once AND the click was
   290 	  // on a node that was found in the set of 
   291 	  //nodes, and now we only search for the second 
   292 	  //node
   293 	  else
   294 	    {
   295 	      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   296 	      target_item=(get_item_at(clicked_x, clicked_y));
   297 	      Graph::NodeIt target_node=INVALID;
   298 	      for (NodeIt i(g); i!=INVALID; ++i)
   299 		{
   300 		  if(nodesmap[i]==target_item)
   301 		    {
   302 		      target_node=i;
   303 		    }
   304 		}
   305 	      //the clicked item is a node, the edge can be drawn
   306 	      if(target_node!=INVALID)
   307 		{
   308 		  if(target_node!=active_node)		
   309 		    {
   310 		      *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   311 
   312 		      //creating new edge
   313 		      active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   314 
   315 		      //initiating values corresponding to new edge in maps
   316 		      mapstorage.initMapsForEdge(active_edge);
   317 	  
   318 		      //calculating coordinates of new edge
   319 		      Gnome::Canvas::Points coos;
   320 		      double x1, x2, y1, y2;
   321 	  
   322 		      active_item->get_bounds(x1, y1, x2, y2);
   323 		      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   324 
   325 		      target_item->get_bounds(x1, y1, x2, y2);
   326 		      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   327 
   328 		      //drawing new edge
   329 		      edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
   330 		      *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   331 		      edgesmap[active_edge]->property_width_pixels().set_value(10);
   332 
   333 		      //redraw nodes to blank terminations of the new edge
   334 		      target_item->raise_to_top();
   335 		      active_item->raise_to_top();
   336 
   337 		      //initializing edge-text as well, to empty string
   338 		      xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
   339 		      text_pos+=(xy<double>(10,10));
   340 
   341 		      edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
   342 		      edgetextmap[active_edge]->property_fill_color().set_value("darkgreen");
   343 
   344 		      //updating its properties
   345 		      mapwin->updateEdge(active_edge);
   346 		    }
   347 		  else
   348 		    {
   349 		      target_node=INVALID;
   350 		      std::cout << "Loop edge is not yet implemented!" << std::endl;
   351 		    }
   352 		}
   353 	      //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
   354 	      else
   355 		{
   356 		  target_item=NULL;
   357 		}
   358 	    }
   359 	}
   360       break;
   361     case GDK_BUTTON_RELEASE:
   362       isbutton=0;
   363       //we clear settings in two cases
   364       //1: the edge is ready (target_item has valid value)
   365       //2: the edge creation is cancelled with right button
   366       if((target_item)||(e->button.button==3))
   367 	{
   368 	  if(active_item)
   369 	    {
   370 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   371 	      active_item=NULL;
   372 	    }
   373 	  if(target_item)
   374 	    {
   375 	      *target_item << Gnome::Canvas::Properties::fill_color("blue");
   376 	      target_item=NULL;
   377 	    }
   378 	  active_node=INVALID;
   379 	  active_edge=INVALID;
   380 	}
   381       break;
   382     default:
   383       break;
   384     }
   385   return false;
   386 }
   387 
   388 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
   389 {
   390   switch(e->type)
   391     {
   392     case GDK_BUTTON_PRESS:
   393       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   394       active_item=(get_item_at(clicked_x, clicked_y));
   395       active_node=INVALID;
   396       active_edge=INVALID;
   397       for (NodeIt i(g); i!=INVALID; ++i)
   398 	{
   399 	  if(nodesmap[i]==active_item)
   400 	    {
   401 	      active_node=i;
   402 	    }
   403 	}
   404       if(active_node==INVALID)
   405 	{
   406 	  for (EdgeIt i(g); i!=INVALID; ++i)
   407 	    {
   408 	      if(edgesmap[i]==active_item)
   409 		{
   410 		  active_edge=i;
   411 		}
   412 	    }
   413 	}
   414       if(active_item)
   415 	{
   416 	  *active_item << Gnome::Canvas::Properties::fill_color("red");
   417 	}
   418       break;
   419 
   420     case GDK_BUTTON_RELEASE:
   421       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   422       if(active_item)
   423 	{
   424 	  if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
   425 	    {
   426 	      if(active_node!=INVALID)
   427 		{
   428 
   429 		  //collecting edges to delete
   430 		  EdgeIt e;
   431 		  std::set<Graph::Edge> edges_to_delete;
   432 
   433 		  g.firstOut(e,active_node);
   434 		  for(;e!=INVALID;g.nextOut(e))
   435 		    {
   436 		      edges_to_delete.insert(e);
   437 		    }
   438 
   439 		  g.firstIn(e,active_node);
   440 		  for(;e!=INVALID;g.nextIn(e))
   441 		    {
   442 		      edges_to_delete.insert(e);
   443 		    }
   444 
   445 		  //deleting collected edges
   446 		  for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
   447 		    {
   448 		      deleteItem(*edge_set_it);
   449 		    }
   450 		  deleteItem(active_node);
   451 		}
   452 	      //a simple edge was chosen
   453 	      else
   454 		{
   455 		  deleteItem(active_edge);
   456 		}
   457 	    }
   458 	  //pointer was moved, deletion is cancelled
   459 	  else
   460 	    {
   461 	      if(active_node!=INVALID)
   462 		{
   463 		  *active_item << Gnome::Canvas::Properties::fill_color("blue");
   464 		}
   465 	      else
   466 		{
   467 		  *active_item << Gnome::Canvas::Properties::fill_color("green");
   468 		}
   469 	    }
   470 	}
   471       //reseting datas
   472       active_item=NULL;
   473       active_edge=INVALID;
   474       active_node=INVALID;
   475       break;
   476 
   477     case GDK_MOTION_NOTIFY:
   478       break;
   479 
   480     default:
   481       break;
   482     }
   483   return false;
   484 }
   485 
   486 bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
   487 {
   488   switch(e->type)
   489     {
   490     case GDK_BUTTON_PRESS:
   491       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   492       active_item=(get_item_at(clicked_x, clicked_y));
   493       active_edge=INVALID;
   494       for (EdgeIt i(g); i!=INVALID; ++i)
   495 	{
   496 	  if(edgesmap[i]==active_item)
   497 	    {
   498 	      active_edge=i;
   499 	    }
   500 	}
   501       if(active_edge!=INVALID)
   502 	{
   503 	  if(canvasentrywidget)
   504 	    {
   505 	      delete(canvasentrywidget);
   506 	    }
   507 	  entrywidget.show();
   508 	  entrywidget.set_text("Hello!");
   509 	  //	  canvasentrywidget=new Gnome::Canvas::Widget(displayed_graph, clicked_x, clicked_y,entrywidget);
   510 	  canvasentrywidget=new Gnome::Canvas::Widget(displayed_graph, e->button.x, e->button.y, entrywidget);
   511 	  canvasentrywidget->property_width().set_value(70);
   512 	  canvasentrywidget->property_height().set_value(50);
   513 	  canvasentrywidget->show();
   514 	  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("red");
   515 	}
   516       active_item=NULL;		// !!!!!!!!!!!!!!!!!!!!!!!!!!!
   517       active_edge=INVALID;	// !!!!!!!!!!!!!!!!!!!!!!!!!!!
   518       break;
   519     default:
   520       break;
   521     }
   522   return false;  
   523 }
   524 
   525 bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
   526 {
   527   e=e;
   528   return false;
   529 }
   530 
   531 void GraphDisplayerCanvas::deleteItem(NodeIt node_to_delete)
   532 {
   533   delete(nodetextmap[node_to_delete]);
   534   delete(nodesmap[node_to_delete]);
   535   g.erase(node_to_delete);
   536 }
   537 
   538 void GraphDisplayerCanvas::deleteItem(EdgeIt edge_to_delete)
   539 {
   540   delete(edgetextmap[edge_to_delete]);
   541   delete(edgesmap[edge_to_delete]);
   542   g.erase(edge_to_delete);
   543 }
   544 
   545 void GraphDisplayerCanvas::deleteItem(Graph::Edge edge_to_delete)
   546 {
   547   delete(edgetextmap[edge_to_delete]);
   548   delete(edgesmap[edge_to_delete]);
   549   g.erase(edge_to_delete);
   550 }
   551 
   552 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
   553 {
   554   new_place+=(xy<double>(10,10));
   555   edgetextmap[active_edge]->property_x().set_value(new_place.x);
   556   edgetextmap[active_edge]->property_y().set_value(new_place.y);
   557 }
   558 
   559 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
   560 {
   561   if(on)
   562     {
   563       if(active_edge!=INVALID)
   564 	{
   565 	  std::cout << "ERROR!!!! Valid edge found!" << std::endl;
   566 	}
   567       else
   568 	{
   569 	  for (EdgeIt i(g); i!=INVALID; ++i)
   570 	    {
   571 	      if(edgesmap[i]==active_bre)
   572 		{
   573 		  active_edge=i;
   574 		}
   575 	    }
   576 	}
   577     }
   578   else
   579     {
   580       if(active_edge!=INVALID)
   581 	{
   582 	  active_edge=INVALID;
   583 	}
   584       else
   585 	{
   586 	  std::cout << "ERROR!!!! Invalid edge found!" << std::endl;
   587 	}
   588     }
   589 
   590 }
   591