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