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