COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas-event.cc @ 34:2cb1fc37f742

gui
Last change on this file since 34:2cb1fc37f742 was 34:2cb1fc37f742, checked in by Hegyi Péter, 19 years ago

EdgeMapEditor? is on its way, but it is far not yet ready.

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