COIN-OR::LEMON - Graph Library

source: lemon-0.x/gui/graph_displayer_canvas-event.cc @ 1562:73c3f5d0079c

Last change on this file since 1562:73c3f5d0079c was 1562:73c3f5d0079c, 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
Line 
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  if(actual_tool!=newtool)
17    {
18
19      actual_handler.disconnect();
20
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        }
36
37      active_item=NULL;
38      target_item=NULL;
39      active_edge=INVALID;     
40      active_node=INVALID;     
41
42
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;
50
51        case CREATE_NODE:
52          actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
53          break;
54
55        case CREATE_EDGE:
56          actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
57          break;
58
59        case ERASER:
60          actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
61          break;
62
63        case EDGE_MAP_EDIT:
64          grab_focus();
65          actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
66          break;
67
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        }
75    }
76}
77
78int GraphDisplayerCanvas::getActualTool()
79{
80  return actual_tool;
81}
82
83bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
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
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));
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
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;
130
131        //repositioning node and its text
132        active_item->move(dx, dy);
133        nodetextmap[active_node]->move(dx, dy);
134
135        clicked_x=new_x;
136        clicked_y=new_y;
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              {
156                edgesmap[ei]->setPoints(coos);
157              }
158            else
159              {
160                edgesmap[ei]->setPoints(coos,true);
161              }
162
163            //reposition of edgetext
164            xy<double> text_pos=edgesmap[ei]->getArrowPos();
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              {
184                edgesmap[ei]->setPoints(coos);
185              }
186            else
187              {
188                edgesmap[ei]->setPoints(coos,true);
189              }
190
191            xy<double> text_pos=edgesmap[ei]->getArrowPos();
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
200  return false;
201}
202
203bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
204{
205  switch(e->type)
206    {
207
208      //draw the new node in red at the clicked place
209    case GDK_2BUTTON_PRESS:
210      std::cout << "double click" << std::endl;
211      break;
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
221      target_item=NULL;
222      target_item=get_item_at(clicked_x, clicked_y);
223
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();
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
233      mapwin->updateNode(active_node);
234
235      break;
236
237      //move the new node
238    case GDK_MOTION_NOTIFY:
239      {
240        GdkEvent * generated=new GdkEvent();
241        generated->motion.x=e->motion.x;
242        generated->motion.y=e->motion.y;
243        generated->type=GDK_MOTION_NOTIFY;
244        moveEventHandler(generated);     
245        break;
246      }
247
248      //finalize the new node
249    case GDK_BUTTON_RELEASE:
250      isbutton=0;
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;
262      active_item=NULL;
263      active_node=INVALID;
264      break;
265    default:
266      break;
267    }
268  return false;
269}
270
271bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
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
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));
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            {
314              window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
315              target_item=(get_item_at(clicked_x, clicked_y));
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                {
327                  if(target_node!=active_node)         
328                    {
329                      *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
330
331                      //creating new edge
332                      active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
333
334                      //initiating values corresponding to new edge in maps
335                      mapstorage.initMapsForEdge(active_edge);
336         
337                      //calculating coordinates of new edge
338                      Gnome::Canvas::Points coos;
339                      double x1, x2, y1, y2;
340         
341                      active_item->get_bounds(x1, y1, x2, y2);
342                      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
343
344                      target_item->get_bounds(x1, y1, x2, y2);
345                      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
346
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);
351
352                      //redraw nodes to blank terminations of the new edge
353                      target_item->raise_to_top();
354                      active_item->raise_to_top();
355
356                      //initializing edge-text as well, to empty string
357                      xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
358                      text_pos+=(xy<double>(10,10));
359
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
364                      mapwin->updateEdge(active_edge);
365                    }
366                  else
367                    {
368                      target_node=INVALID;
369                      std::cout << "Loop edge is not yet implemented!" << std::endl;
370                    }
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
407bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
408{
409  switch(e->type)
410    {
411    case GDK_BUTTON_PRESS:
412      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
413      active_item=(get_item_at(clicked_x, clicked_y));
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        }
433      if(active_item)
434        {
435          *active_item << Gnome::Canvas::Properties::fill_color("red");
436        }
437      break;
438
439    case GDK_BUTTON_RELEASE:
440      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
441      if(active_item)
442        {
443          if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
444            {
445              if(active_node!=INVALID)
446                {
447
448                  //collecting edges to delete
449                  EdgeIt e;
450                  std::set<Graph::Edge> edges_to_delete;
451
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
473                {
474                  deleteItem(active_edge);
475                }
476            }
477          //pointer was moved, deletion is cancelled
478          else
479            {
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                }
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    }
502  return false;
503}
504
505bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
506{
507  switch(e->type)
508    {
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      }
523    case GDK_BUTTON_PRESS:
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      }
563    default:
564      break;
565    }
566  return false; 
567}
568
569bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
570{
571  e=e;
572  return false;
573}
574
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
583void GraphDisplayerCanvas::deleteItem(NodeIt node_to_delete)
584{
585  delete(nodetextmap[node_to_delete]);
586  delete(nodesmap[node_to_delete]);
587  g.erase(node_to_delete);
588}
589
590void GraphDisplayerCanvas::deleteItem(EdgeIt edge_to_delete)
591{
592  delete(edgetextmap[edge_to_delete]);
593  delete(edgesmap[edge_to_delete]);
594  g.erase(edge_to_delete);
595}
596
597void GraphDisplayerCanvas::deleteItem(Graph::Edge edge_to_delete)
598{
599  delete(edgetextmap[edge_to_delete]);
600  delete(edgesmap[edge_to_delete]);
601  g.erase(edge_to_delete);
602}
603
604void GraphDisplayerCanvas::textReposition(xy<double> new_place)
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
611void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
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}
643
Note: See TracBrowser for help on using the repository browser.