COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas-event.cc @ 32:1f45545f124c

gui
Last change on this file since 32:1f45545f124c was 32:1f45545f124c, checked in by Hegyi Péter, 15 years ago

Editors are based.

  • Property exe set to *
File size: 14.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  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  switch(newtool)
29    {
30    case MOVE:
31      actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
32      break;
33
34    case CREATE_NODE:
35      actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
36      break;
37
38    case CREATE_EDGE:
39      actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
40      break;
41
42    case ERASER:
43      actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
44      break;
45
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
54    default:
55      break;
56    }
57}
58
59int GraphDisplayerCanvas::getActualTool()
60{
61  return actual_tool;
62}
63
64bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
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
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));
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
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;
111
112        //repositioning node and its text
113        active_item->move(dx, dy);
114        nodetextmap[active_node]->move(dx, dy);
115
116        clicked_x=new_x;
117        clicked_y=new_y;
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              {
137                edgesmap[ei]->setPoints(coos);
138              }
139            else
140              {
141                edgesmap[ei]->setPoints(coos,true);
142              }
143
144            //reposition of edgetext
145            xy<double> text_pos=edgesmap[ei]->getArrowPos();
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              {
165                edgesmap[ei]->setPoints(coos);
166              }
167            else
168              {
169                edgesmap[ei]->setPoints(coos,true);
170              }
171
172            xy<double> text_pos=edgesmap[ei]->getArrowPos();
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
181  return false;
182}
183
184bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
185{
186  switch(e->type)
187    {
188
189      //draw the new node in red at the clicked place
190    case GDK_2BUTTON_PRESS:
191      std::cout << "double click" << std::endl;
192      break;
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
202      target_item=NULL;
203      target_item=get_item_at(clicked_x, clicked_y);
204
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();
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
214      mapwin->updateNode(active_node);
215
216      break;
217
218      //move the new node
219    case GDK_MOTION_NOTIFY:
220      {
221        GdkEvent * generated=new GdkEvent();
222        generated->motion.x=e->motion.x;
223        generated->motion.y=e->motion.y;
224        generated->type=GDK_MOTION_NOTIFY;
225        moveEventHandler(generated);     
226        break;
227      }
228
229      //finalize the new node
230    case GDK_BUTTON_RELEASE:
231      isbutton=0;
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;
243      active_item=NULL;
244      active_node=INVALID;
245      break;
246    default:
247      break;
248    }
249  return false;
250}
251
252bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
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
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));
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            {
295              window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
296              target_item=(get_item_at(clicked_x, clicked_y));
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                {
308                  if(target_node!=active_node)         
309                    {
310                      *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
311
312                      //creating new edge
313                      active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
314
315                      //initiating values corresponding to new edge in maps
316                      mapstorage.initMapsForEdge(active_edge);
317         
318                      //calculating coordinates of new edge
319                      Gnome::Canvas::Points coos;
320                      double x1, x2, y1, y2;
321         
322                      active_item->get_bounds(x1, y1, x2, y2);
323                      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
324
325                      target_item->get_bounds(x1, y1, x2, y2);
326                      coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
327
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);
332
333                      //redraw nodes to blank terminations of the new edge
334                      target_item->raise_to_top();
335                      active_item->raise_to_top();
336
337                      //initializing edge-text as well, to empty string
338                      xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
339                      text_pos+=(xy<double>(10,10));
340
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
345                      mapwin->updateEdge(active_edge);
346                    }
347                  else
348                    {
349                      target_node=INVALID;
350                      std::cout << "Loop edge is not yet implemented!" << std::endl;
351                    }
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
388bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
389{
390  switch(e->type)
391    {
392    case GDK_BUTTON_PRESS:
393      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
394      active_item=(get_item_at(clicked_x, clicked_y));
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        }
414      if(active_item)
415        {
416          *active_item << Gnome::Canvas::Properties::fill_color("red");
417        }
418      break;
419
420    case GDK_BUTTON_RELEASE:
421      window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
422      if(active_item)
423        {
424          if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
425            {
426              if(active_node!=INVALID)
427                {
428
429                  //collecting edges to delete
430                  EdgeIt e;
431                  std::set<Graph::Edge> edges_to_delete;
432
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
454                {
455                  deleteItem(active_edge);
456                }
457            }
458          //pointer was moved, deletion is cancelled
459          else
460            {
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                }
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    }
483  return false;
484}
485
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
531void GraphDisplayerCanvas::deleteItem(NodeIt node_to_delete)
532{
533  delete(nodetextmap[node_to_delete]);
534  delete(nodesmap[node_to_delete]);
535  g.erase(node_to_delete);
536}
537
538void GraphDisplayerCanvas::deleteItem(EdgeIt edge_to_delete)
539{
540  delete(edgetextmap[edge_to_delete]);
541  delete(edgesmap[edge_to_delete]);
542  g.erase(edge_to_delete);
543}
544
545void GraphDisplayerCanvas::deleteItem(Graph::Edge edge_to_delete)
546{
547  delete(edgetextmap[edge_to_delete]);
548  delete(edgesmap[edge_to_delete]);
549  g.erase(edge_to_delete);
550}
551
552void GraphDisplayerCanvas::textReposition(xy<double> new_place)
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
559void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
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}
591
Note: See TracBrowser for help on using the repository browser.