graph_displayer_canvas-event.cc
author hegyi
Fri, 24 Jun 2005 07:58:18 +0000
branchgui
changeset 27 e2c86ae158cf
child 28 fa28f1071bd6
permissions -rwxr-xr-x
File graph_displayer is split in functional parts.
     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         active_item->move(dx, dy);
   103 
   104         clicked_x=e->motion.x;
   105         clicked_y=e->motion.y;
   106 
   107 	//all the edges connected to the moved point has to be redrawn
   108         EdgeIt ei;
   109 
   110         g.firstOut(ei,active_node);
   111 
   112         for(;ei!=INVALID;g.nextOut(ei))
   113         {
   114             Gnome::Canvas::Points coos;
   115             double x1, x2, y1, y2;
   116 
   117             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   118             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   119 
   120             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   121             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   122 
   123 	    if(isbutton==3)
   124 	      {
   125 		edgesmap[ei]->set_points(coos);
   126 	      }
   127 	    else
   128 	      {
   129 		edgesmap[ei]->set_points(coos,true);
   130 	      }
   131 
   132 	    xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
   133 	    text_pos+=(xy<double>(10,10));
   134 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   135 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   136         }
   137 
   138         g.firstIn(ei,active_node);
   139         for(;ei!=INVALID;g.nextIn(ei))
   140         {
   141             Gnome::Canvas::Points coos;
   142             double x1, x2, y1, y2;
   143 
   144             nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
   145             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   146 
   147             nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
   148             coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   149 
   150 	    if(isbutton==3)
   151 	      {
   152 		edgesmap[ei]->set_points(coos);
   153 	      }
   154 	    else
   155 	      {
   156 		edgesmap[ei]->set_points(coos,true);
   157 	      }
   158 
   159 	    xy<double> text_pos=edgesmap[ei]->get_arrow_pos();
   160 	    text_pos+=(xy<double>(10,10));
   161 	    edgetextmap[ei]->property_x().set_value(text_pos.x);
   162 	    edgetextmap[ei]->property_y().set_value(text_pos.y);
   163         }
   164       }
   165     default: break;
   166   }
   167 
   168   return true;
   169 }
   170 
   171 bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
   172 {
   173   switch(e->type)
   174     {
   175 
   176       //draw the new node in red at the clicked place
   177     case GDK_BUTTON_PRESS:
   178       isbutton=1;
   179 
   180       active_node=NodeIt(g,g.addNode());
   181 
   182       //initiating values corresponding to new node in maps
   183       
   184 
   185       window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   186 
   187       nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
   188       active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
   189       *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   190       *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
   191       (nodesmap[active_node])->show();
   192       break;
   193 
   194       //move the new node
   195     case GDK_MOTION_NOTIFY:
   196       {
   197 	double world_motion_x, world_motion_y;
   198 	GdkEvent * generated=new GdkEvent();
   199 	window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
   200 	generated->motion.x=world_motion_x;
   201 	generated->motion.y=world_motion_y;
   202 	generated->type=GDK_MOTION_NOTIFY;
   203 	move_event_handler(generated);      
   204 	break;
   205       }
   206 
   207       //finalize the new node
   208     case GDK_BUTTON_RELEASE:
   209       isbutton=0;
   210       *active_item << Gnome::Canvas::Properties::fill_color("blue");
   211       active_item=NULL;
   212       active_node=INVALID;
   213       updateScrollRegion();
   214       break;
   215     default:
   216       break;
   217     }
   218   return false;
   219 }
   220 
   221 bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
   222 {
   223   switch(e->type)
   224     {
   225     case GDK_BUTTON_PRESS:
   226       //in edge creation right button has special meaning
   227       if(e->button.button!=3)
   228 	{
   229 	  //there is not yet selected node
   230 	  if(active_node==INVALID)
   231 	    {
   232 	      //we mark the location of the event to be able to calculate parameters of dragging
   233 	      clicked_x=e->button.x;
   234 	      clicked_y=e->button.y;
   235 	      active_item=(get_item_at(e->button.x, e->button.y));
   236 	      active_node=INVALID;
   237 	      for (NodeIt i(g); i!=INVALID; ++i)
   238 		{
   239 		  if(nodesmap[i]==active_item)
   240 		    {
   241 		      active_node=i;
   242 		    }
   243 		}
   244 	      //the clicked item is really a node
   245 	      if(active_node!=INVALID)
   246 		{
   247 		  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   248 		  isbutton=1;
   249 		}
   250 	      //clicked item was not a node. It could be e.g. edge.
   251 	      else
   252 		{
   253 		  active_item=NULL;
   254 		}
   255 	    }
   256 	  //we only have to do sg. if the mouse button
   257 	  // is pressed already once AND the click was
   258 	  // on a node that was found in the set of 
   259 	  //nodes, and now we only search for the second 
   260 	  //node
   261 	  else
   262 	    {
   263 	      target_item=(get_item_at(e->button.x, e->button.y));
   264 	      Graph::NodeIt target_node=INVALID;
   265 	      for (NodeIt i(g); i!=INVALID; ++i)
   266 		{
   267 		  if(nodesmap[i]==target_item)
   268 		    {
   269 		      target_node=i;
   270 		    }
   271 		}
   272 	      //the clicked item is a node, the edge can be drawn
   273 	      if(target_node!=INVALID)
   274 		{
   275 		  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   276 
   277 		  //creating new edge
   278 		  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   279 
   280 		  //initiating values corresponding to new edge in maps
   281 		  mapstorage.init_maps_for_edge(active_edge);
   282 	  
   283 		  //calculating coordinates of new edge
   284 		  Gnome::Canvas::Points coos;
   285 		  double x1, x2, y1, y2;
   286 	  
   287 		  active_item->get_bounds(x1, y1, x2, y2);
   288 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   289 
   290 		  target_item->get_bounds(x1, y1, x2, y2);
   291 		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   292 
   293 		  //drawing new edge
   294 		  edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
   295 		  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   296 		  edgesmap[active_edge]->property_width_pixels().set_value(10);
   297 
   298 		  //redraw nodes to blank terminations of the new edge
   299 		  target_item->raise_to_top();
   300 		  active_item->raise_to_top();
   301 
   302 		  //initializing edge-text as well, to empty string
   303 		  xy<double> text_pos=edgesmap[active_edge]->get_arrow_pos();
   304 		  text_pos+=(xy<double>(10,10));
   305 
   306 		  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
   307 		  edgetextmap[active_edge]->property_fill_color().set_value("black");
   308 		}
   309 	      //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
   310 	      else
   311 		{
   312 		  target_item=NULL;
   313 		}
   314 	    }
   315 	}
   316       break;
   317     case GDK_BUTTON_RELEASE:
   318       isbutton=0;
   319       //we clear settings in two cases
   320       //1: the edge is ready (target_item has valid value)
   321       //2: the edge creation is cancelled with right button
   322       if((target_item)||(e->button.button==3))
   323 	{
   324 	  if(active_item)
   325 	    {
   326 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   327 	      active_item=NULL;
   328 	    }
   329 	  if(target_item)
   330 	    {
   331 	      *target_item << Gnome::Canvas::Properties::fill_color("blue");
   332 	      target_item=NULL;
   333 	    }
   334 	  active_node=INVALID;
   335 	  active_edge=INVALID;
   336 	}
   337       break;
   338     default:
   339       break;
   340     }
   341   return false;
   342 }
   343 
   344 bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
   345 {
   346   switch(e->type)
   347     {
   348     case GDK_BUTTON_PRESS:
   349       active_item=(get_item_at(e->button.x, e->button.y));
   350       active_node=INVALID;
   351       active_edge=INVALID;
   352       for (NodeIt i(g); i!=INVALID; ++i)
   353 	{
   354 	  if(nodesmap[i]==active_item)
   355 	    {
   356 	      active_node=i;
   357 	    }
   358 	}
   359       if(active_node==INVALID)
   360 	{
   361 	  for (EdgeIt i(g); i!=INVALID; ++i)
   362 	    {
   363 	      if(edgesmap[i]==active_item)
   364 		{
   365 		  active_edge=i;
   366 		}
   367 	    }
   368 	}
   369     *active_item << Gnome::Canvas::Properties::fill_color("red");
   370       break;
   371 
   372     case GDK_BUTTON_RELEASE:
   373       if(active_item==(get_item_at(e->button.x, e->button.y)))
   374 	{
   375 	  if(active_node!=INVALID)
   376 	    {
   377 
   378 	      //collecting edges to delete
   379 	      EdgeIt e;
   380 	      std::set<Graph::Edge> edges_to_delete;
   381 
   382 	      g.firstOut(e,active_node);
   383 	      for(;e!=INVALID;g.nextOut(e))
   384 		{
   385 		      edges_to_delete.insert(e);
   386 		}
   387 
   388 	      g.firstIn(e,active_node);
   389 	      for(;e!=INVALID;g.nextIn(e))
   390 		{
   391 		      edges_to_delete.insert(e);
   392 		}
   393 
   394 	      //deleting collected edges
   395 	      for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
   396 		{
   397 		  delete_item(*edge_set_it);
   398 		}
   399 	      delete_item(active_node);
   400 	    }
   401 	  //a simple edge was chosen
   402 	  else
   403 	    {
   404 	      delete_item(active_edge);
   405 	    }
   406 
   407 	  
   408 	}
   409       //pointer was moved, deletion is cancelled
   410       else
   411 	{
   412 	  if(active_node!=INVALID)
   413 	    {
   414 	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   415 	    }
   416 	  else
   417 	    {
   418 	      *active_item << Gnome::Canvas::Properties::fill_color("green");
   419 	    }
   420 	}
   421       //reseting datas
   422       active_item=NULL;
   423       active_edge=INVALID;
   424       active_node=INVALID;
   425       break;
   426 
   427     case GDK_MOTION_NOTIFY:
   428       break;
   429 
   430     default:
   431       break;
   432     }
   433   return true;
   434 }
   435 
   436 void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
   437 {
   438   delete(nodesmap[node_to_delete]);
   439   g.erase(node_to_delete);
   440 }
   441 
   442 void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
   443 {
   444   delete(edgesmap[edge_to_delete]);
   445   g.erase(edge_to_delete);
   446 }
   447 
   448 void GraphDisplayerCanvas::delete_item(Graph::Edge edge_to_delete)
   449 {
   450   delete(edgesmap[edge_to_delete]);
   451   g.erase(edge_to_delete);
   452 }
   453 
   454 void GraphDisplayerCanvas::text_reposition(xy<double> new_place)
   455 {
   456   new_place+=(xy<double>(10,10));
   457   edgetextmap[active_edge]->property_x().set_value(new_place.x);
   458   edgetextmap[active_edge]->property_y().set_value(new_place.y);
   459 }
   460 
   461 void GraphDisplayerCanvas::toggle_edge_activity(BrokenEdge* active_bre, bool on)
   462 {
   463   if(on)
   464     {
   465       if(active_edge!=INVALID)
   466 	{
   467 	  std::cout << "ERROR!!!! Valid edge found!" << std::endl;
   468 	}
   469       else
   470 	{
   471 	  for (EdgeIt i(g); i!=INVALID; ++i)
   472 	    {
   473 	      if(edgesmap[i]==active_bre)
   474 		{
   475 		  active_edge=i;
   476 		}
   477 	    }
   478 	}
   479     }
   480   else
   481     {
   482       if(active_edge!=INVALID)
   483 	{
   484 	  active_edge=INVALID;
   485 	}
   486       else
   487 	{
   488 	  std::cout << "ERROR!!!! Invalid edge found!" << std::endl;
   489 	}
   490     }
   491 
   492 }