graph_displayer_canvas-event.cc
branchgui
changeset 27 e2c86ae158cf
child 28 fa28f1071bd6
equal deleted inserted replaced
-1:000000000000 0:0b9af95340f5
       
     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 }