COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas-event.cc @ 31:66e85f44a66f

gui
Last change on this file since 31:66e85f44a66f was 31:66e85f44a66f, checked in by Hegyi Péter, 19 years ago

Uh, long comment arrives... Zoom update does not happen after editorial steps. Nodes initial color is light blue, if there is any item under them. Strange node-text relations disappeared. Initial values of new items are given now in a more common way. The wood-cutter way of handling default values of properties is now changed.

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