COIN-OR::LEMON - Graph Library

source: lemon-0.x/gui/graph_displayer_canvas-event.cc @ 1550:4dcbb4ab1d7a

Last change on this file since 1550:4dcbb4ab1d7a was 1550:4dcbb4ab1d7a, checked in by Hegyi Péter, 19 years ago

Editors are based.

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