COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas-event.cc @ 33:8dc87bc15ec5

gui
Last change on this file since 33:8dc87bc15ec5 was 33:8dc87bc15ec5, checked in by Hegyi Péter, 15 years ago

Developing of edgemap editing is started.

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