Correcting concept checks.
1 #include <graph_displayer_canvas.h>
4 GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm, MapStorage & ms):g(gr),nodesmap(g),edgesmap(g),edgetextmap(g),displayed_graph(*(root()), 0, 0),mapstorage(ms),isbutton(false),active_item(NULL),target_item(NULL)
7 actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
12 //set_center_scroll_region(true);
14 //first edges are drawn, to hide joining with nodes later
16 for (EdgeIt i(g); i!=INVALID; ++i)
19 //drawing green lines, coordinates are from cm
21 Gnome::Canvas::Points coos;
22 coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
23 coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
25 edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos);
26 *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
27 edgesmap[i]->property_width_pixels().set_value(10);
29 //initializing edge-text as well, to empty string
31 double x1, x2, y1, y2;
32 edgesmap[i]->get_bounds(x1, y1, x2, y2);
34 edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
35 edgetextmap[i]->property_fill_color().set_value("black");
38 //afterwards nodes come to be drawn
41 int maxx=0, maxy=0, minx=(int)cm[i].x, miny=(int)cm[i].y;
43 for (; i!=INVALID; ++i)
45 //minimum and maximum is gathered to be able to zoom to the graph correctly (whole figure should be seen)
47 if(cm[i].x>maxx)maxx=(int)cm[i].x;
48 if(cm[i].y>maxy)maxy=(int)cm[i].y;
49 if(cm[i].x<minx)minx=(int)cm[i].x;
50 if(cm[i].y<miny)miny=(int)cm[i].y;
52 //drawing bule nodes, with black line around them
54 nodesmap[i]=new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
55 *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
56 *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
57 //!!!!!!! (nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
63 GraphDisplayerCanvas::~GraphDisplayerCanvas()
66 //writing out the end state of the graph
67 //\todo all the maps has to be write out!
69 Graph::NodeMap <int> id(g);
70 Graph::NodeMap <double> xc(g);
71 Graph::NodeMap <double> yc(g);
75 for (NodeIt i(g); i!=INVALID; ++i)
78 nodesmap[i]->get_bounds(x1, y1, x2, y2);
85 GraphWriter<Graph> writer(std::cout,g);
87 writer.writeNodeMap("id", id);
88 writer.writeNodeMap("coordinates_x", xc);
89 writer.writeNodeMap("coordinates_y", yc);
93 int GraphDisplayerCanvas::changeLineWidth (std::string mapname)
95 for (EdgeIt i(g); i!=INVALID; ++i)
97 int w=(int)(*(mapstorage.edgemap_storage)[mapname])[i];
98 edgesmap[i]->property_width_pixels().set_value(w);
103 int GraphDisplayerCanvas::changeColor (std::string mapname)
106 //function maps the range of the maximum and
107 //the minimum of the nodemap to the range of
110 for (EdgeIt i(g); i!=INVALID; ++i)
112 double w=(*(mapstorage.edgemap_storage)[mapname])[i];
113 double max=mapstorage.maxOfEdgeMap(mapname);
114 double min=mapstorage.minOfEdgeMap(mapname);
116 //std::cout<<w<<" "<<max<<" "<<min<<" "<<100*(w-min)/(max-min)<<std::endl;
120 color.set_rgb_p (0, 100*(w-min)/(max-min), 0);
124 color.set_rgb_p (0, 100, 0);
127 edgesmap[i]->property_fill_color_gdk().set_value(color);
132 int GraphDisplayerCanvas::changeText (std::string mapname)
135 //the number in the map will be written on the edge
136 //EXCEPT when the name of the map is Text, because
137 //in that case empty string will be written, because
138 //that is the deleter map
139 //\todo isn't it a bit woodcutter?
141 for (EdgeIt i(g); i!=INVALID; ++i)
145 double number=(*(mapstorage.edgemap_storage)[mapname])[i];
146 int length=(int)(floor(log(number)/log(10)))+1;
147 int maxpos=(int)(pow(10,length-1));
148 int strl=length+1+RANGE;
149 char * str=new char[strl];
153 for(int j=0;j<strl;j++)
157 int digit=(int)(number/maxpos);
159 number-=digit*maxpos;
164 edgetextmap[i]->property_text().set_value(str);
168 edgetextmap[i]->property_text().set_value("");
174 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
178 case GDK_BUTTON_PRESS:
179 //we mark the location of the event to be able to calculate parameters of dragging
180 clicked_x=e->button.x;
181 clicked_y=e->button.y;
182 active_item=(get_item_at(e->button.x, e->button.y));
185 case GDK_BUTTON_RELEASE:
188 updateScrollRegion();
190 case GDK_MOTION_NOTIFY:
191 //we only have to do sg. if the mouse button is pressed
194 //new coordinates will be the old values,
195 //because the item will be moved to the
196 //new coordinate therefore the new movement
197 //has to be calculated from here
199 double dx=e->motion.x-clicked_x;
200 double dy=e->motion.y-clicked_y;
201 active_item->move(dx, dy);
202 clicked_x=e->motion.x;
203 clicked_y=e->motion.y;
205 //all the edges connected to the moved point has to be redrawn
209 for(;e!=INVALID;g.nextOut(e))
211 Gnome::Canvas::Points coos;
212 double x1, x2, y1, y2;
214 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
215 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
217 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
218 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
220 edgesmap[e]->property_points().set_value(coos);
222 edgesmap[e]->get_bounds(x1, y1, x2, y2);
224 edgetextmap[e]->property_x().set_value((x1+x2)/2);
225 edgetextmap[e]->property_y().set_value((y1+y2)/2);
229 for(;e!=INVALID;g.nextIn(e))
231 Gnome::Canvas::Points coos;
232 double x1, x2, y1, y2;
234 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
235 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
237 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
238 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
240 edgesmap[e]->property_points().set_value(coos);
242 edgesmap[e]->get_bounds(x1, y1, x2, y2);
244 edgetextmap[e]->property_x().set_value((x1+x2)/2);
245 edgetextmap[e]->property_y().set_value((y1+y2)/2);
253 bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
255 Gnome::Canvas::CanvasAA::on_expose_event(event);
261 void GraphDisplayerCanvas::zoomIn()
264 (1.0 + (double) zoom_step / 100.0) * get_pixels_per_unit());
267 void GraphDisplayerCanvas::zoomOut()
270 (1.0 - (double) zoom_step / 100.0) * get_pixels_per_unit());
273 void GraphDisplayerCanvas::zoomFit()
275 // get the height and width of the canvas
276 Gtk::Allocation a = get_allocation();
277 int aw = a.get_width();
278 int ah = a.get_height();
280 aw -= 5; if (aw < 0) aw = 0;
281 ah -= 5; if (ah < 0) ah = 0;
283 // get the bounding box of the graph
284 double wx1, wy1, wx2, wy2;
285 Gnome::Canvas::Item* pCanvasItem = root();
286 pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
288 // fit the graph to the window
289 double ppu1 = (double) aw / fabs(wx2 - wx1);
290 double ppu2 = (double) ah / fabs(wy2 - wy1);
291 set_pixels_per_unit((ppu1 < ppu2) ? ppu1 : ppu2);
294 void GraphDisplayerCanvas::zoom100()
296 set_pixels_per_unit(1.0);
299 void GraphDisplayerCanvas::updateScrollRegion()
301 double wx1, wy1, wx2, wy2;
302 Gnome::Canvas::Item* pCanvasItem = root();
303 pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
304 set_scroll_region(wx1, wy1, wx2, wy2);
307 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
309 actual_handler.disconnect();
314 actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
317 //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
319 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
323 actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
327 actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraser_event_handler), false);
335 bool GraphDisplayerCanvas::move_event_handler(GdkEvent* e)
339 case GDK_BUTTON_PRESS:
340 //we mark the location of the event to be able to calculate parameters of dragging
341 clicked_x=e->button.x;
342 clicked_y=e->button.y;
343 active_item=(get_item_at(e->button.x, e->button.y));
345 for (NodeIt i(g); i!=INVALID; ++i)
347 if(nodesmap[i]==active_item)
354 case GDK_BUTTON_RELEASE:
358 updateScrollRegion();
360 case GDK_MOTION_NOTIFY:
361 //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
362 if(active_node!=INVALID)
364 //new coordinates will be the old values,
365 //because the item will be moved to the
366 //new coordinate therefore the new movement
367 //has to be calculated from here
369 double dx=e->motion.x-clicked_x;
370 double dy=e->motion.y-clicked_y;
372 active_item->move(dx, dy);
374 clicked_x=e->motion.x;
375 clicked_y=e->motion.y;
377 //all the edges connected to the moved point has to be redrawn
380 g.firstOut(e,active_node);
382 for(;e!=INVALID;g.nextOut(e))
384 Gnome::Canvas::Points coos;
385 double x1, x2, y1, y2;
387 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
388 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
390 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
391 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
393 edgesmap[e]->property_points().set_value(coos);
395 edgesmap[e]->get_bounds(x1, y1, x2, y2);
397 edgetextmap[e]->property_x().set_value((x1+x2)/2);
398 edgetextmap[e]->property_y().set_value((y1+y2)/2);
401 g.firstIn(e,active_node);
402 for(;e!=INVALID;g.nextIn(e))
404 Gnome::Canvas::Points coos;
405 double x1, x2, y1, y2;
407 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
408 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
410 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
411 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
413 edgesmap[e]->property_points().set_value(coos);
415 edgesmap[e]->get_bounds(x1, y1, x2, y2);
417 edgetextmap[e]->property_x().set_value((x1+x2)/2);
418 edgetextmap[e]->property_y().set_value((y1+y2)/2);
427 bool GraphDisplayerCanvas::create_node_event_handler(GdkEvent* e)
432 //draw the new node in red at the clicked place
433 case GDK_BUTTON_PRESS:
436 active_node=NodeIt(g,g.addNode());
438 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
440 nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
441 active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
442 *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
443 *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
444 (nodesmap[active_node])->show();
448 case GDK_MOTION_NOTIFY:
450 double world_motion_x, world_motion_y;
451 GdkEvent * generated=new GdkEvent();
452 window_to_world (e->motion.x, e->motion.y, world_motion_x, world_motion_y);
453 generated->motion.x=world_motion_x;
454 generated->motion.y=world_motion_y;
455 generated->type=GDK_MOTION_NOTIFY;
456 move_event_handler(generated);
460 //finalize the new node
461 case GDK_BUTTON_RELEASE:
463 *active_item << Gnome::Canvas::Properties::fill_color("blue");
466 updateScrollRegion();
474 bool GraphDisplayerCanvas::create_edge_event_handler(GdkEvent* e)
478 case GDK_BUTTON_PRESS:
479 //in edge creatino right button has special meaning
480 if(e->button.button!=3)
482 //there is not yet selected node
483 if(active_node==INVALID)
485 //we mark the location of the event to be able to calculate parameters of dragging
486 clicked_x=e->button.x;
487 clicked_y=e->button.y;
488 active_item=(get_item_at(e->button.x, e->button.y));
490 for (NodeIt i(g); i!=INVALID; ++i)
492 if(nodesmap[i]==active_item)
497 //the clicked item is really a node
498 if(active_node!=INVALID)
500 *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
503 //clicked item was not a node. It could be e.g. edge.
509 //we only have to do sg. if the mouse button
510 // is pressed already once AND the click was
511 // on a node that was found in the set of
512 //nodes, and now we only search for the second
516 target_item=(get_item_at(e->button.x, e->button.y));
517 Graph::NodeIt target_node=INVALID;
518 for (NodeIt i(g); i!=INVALID; ++i)
520 if(nodesmap[i]==target_item)
525 //the clicked item is a node, the edge can be drawn
526 if(target_node!=INVALID)
528 *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
531 active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
533 //calculating coordinates of new edge
534 Gnome::Canvas::Points coos;
535 double x1, x2, y1, y2;
537 active_item->get_bounds(x1, y1, x2, y2);
538 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
540 target_item->get_bounds(x1, y1, x2, y2);
541 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
544 edgesmap[active_edge]=new Gnome::Canvas::Line(displayed_graph, coos);
545 *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
546 edgesmap[active_edge]->property_width_pixels().set_value(10);
548 //redraw nodes to blank terminations of the new edge
549 target_item->raise_to_top();
550 active_item->raise_to_top();
552 //initializing edge-text as well, to empty string
553 edgesmap[active_edge]->get_bounds(x1, y1, x2, y2);
554 edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
555 edgetextmap[active_edge]->property_fill_color().set_value("black");
557 //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
565 case GDK_BUTTON_RELEASE:
567 //we clear settings in two cases
568 //1: the edge is ready (target_item has valid value)
569 //2: the edge creation is cancelled with right button
570 if((target_item)||(e->button.button==3))
574 *active_item << Gnome::Canvas::Properties::fill_color("blue");
579 *target_item << Gnome::Canvas::Properties::fill_color("blue");
592 bool GraphDisplayerCanvas::eraser_event_handler(GdkEvent* e)
596 case GDK_BUTTON_PRESS:
597 active_item=(get_item_at(e->button.x, e->button.y));
600 for (NodeIt i(g); i!=INVALID; ++i)
602 if(nodesmap[i]==active_item)
607 if(active_node==INVALID)
609 for (EdgeIt i(g); i!=INVALID; ++i)
611 if(edgesmap[i]==active_item)
617 *active_item << Gnome::Canvas::Properties::fill_color("red");
620 case GDK_BUTTON_RELEASE:
621 if(active_item==(get_item_at(e->button.x, e->button.y)))
623 if(active_node!=INVALID)
626 // g.firstOut(e,active_node);
627 // for(;e!=INVALID;g.nextOut(e))
629 // if(e!=INVALID)delete_item(e);
632 // g.firstIn(e,active_node);
633 // for(;e!=INVALID;g.nextIn(e))
635 // if(e!=INVALID)delete_item(e);
637 for (EdgeIt i(g); i!=INVALID; ++i)
639 //std::cout << g.source(i).id << "-" << g.target(i).id << " " << active_node.id << std::endl;
640 if((g.source(i)==active_node)||(g.target(i)==active_node))
645 delete_item(active_node);
649 delete_item(active_edge);
656 if(active_node!=INVALID)
658 *active_item << Gnome::Canvas::Properties::fill_color("blue");
662 *active_item << Gnome::Canvas::Properties::fill_color("green");
670 case GDK_MOTION_NOTIFY:
679 void GraphDisplayerCanvas::delete_item(NodeIt node_to_delete)
681 delete(nodesmap[node_to_delete]);
682 g.erase(node_to_delete);
685 void GraphDisplayerCanvas::delete_item(EdgeIt edge_to_delete)
687 delete(edgesmap[edge_to_delete]);
688 g.erase(edge_to_delete);