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