Graph input-output demo, some documentation.
1 #include <graph_displayer_canvas.h>
2 #include <broken_edge.h>
6 bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
8 Gnome::Canvas::CanvasAA::on_expose_event(event);
14 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
16 actual_handler.disconnect();
18 if(actual_tool==CREATE_EDGE)
20 GdkEvent * generated=new GdkEvent();
21 generated->type=GDK_BUTTON_RELEASE;
22 generated->button.button=3;
23 createEdgeEventHandler(generated);
31 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
35 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
39 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
43 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
51 int GraphDisplayerCanvas::getActualTool()
56 bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
60 case GDK_BUTTON_PRESS:
61 //we mark the location of the event to be able to calculate parameters of dragging
62 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
64 active_item=(get_item_at(clicked_x, clicked_y));
66 for (NodeIt i(g); i!=INVALID; ++i)
68 if(nodesmap[i]==active_item)
73 switch(e->button.button)
83 case GDK_BUTTON_RELEASE:
88 case GDK_MOTION_NOTIFY:
89 //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
90 if(active_node!=INVALID)
92 //new coordinates will be the old values,
93 //because the item will be moved to the
94 //new coordinate therefore the new movement
95 //has to be calculated from here
99 window_to_world (e->motion.x, e->motion.y, new_x, new_y);
101 double dx=new_x-clicked_x;
102 double dy=new_y-clicked_y;
104 //repositioning node and its text
105 active_item->move(dx, dy);
106 nodetextmap[active_node]->move(dx, dy);
111 //all the edges connected to the moved point has to be redrawn
114 g.firstOut(ei,active_node);
116 for(;ei!=INVALID;g.nextOut(ei))
118 Gnome::Canvas::Points coos;
119 double x1, x2, y1, y2;
121 nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
122 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
124 nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
125 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
129 edgesmap[ei]->setPoints(coos);
133 edgesmap[ei]->setPoints(coos,true);
136 //reposition of edgetext
137 xy<double> text_pos=edgesmap[ei]->getArrowPos();
138 text_pos+=(xy<double>(10,10));
139 edgetextmap[ei]->property_x().set_value(text_pos.x);
140 edgetextmap[ei]->property_y().set_value(text_pos.y);
143 g.firstIn(ei,active_node);
144 for(;ei!=INVALID;g.nextIn(ei))
146 Gnome::Canvas::Points coos;
147 double x1, x2, y1, y2;
149 nodesmap[g.source(ei)]->get_bounds(x1, y1, x2, y2);
150 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
152 nodesmap[g.target(ei)]->get_bounds(x1, y1, x2, y2);
153 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
157 edgesmap[ei]->setPoints(coos);
161 edgesmap[ei]->setPoints(coos,true);
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);
176 bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
181 //draw the new node in red at the clicked place
182 case GDK_2BUTTON_PRESS:
183 std::cout << "double click" << std::endl;
185 case GDK_BUTTON_PRESS:
188 active_node=NodeIt(g,g.addNode());
190 //initiating values corresponding to new node in maps
192 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
195 target_item=get_item_at(clicked_x, clicked_y);
197 nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph, clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
198 active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
199 *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
200 *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
201 (nodesmap[active_node])->show();
203 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, "");
204 nodetextmap[active_node]->property_fill_color().set_value("darkblue");
206 mapwin->updateNode(active_node);
211 case GDK_MOTION_NOTIFY:
213 double world_motion_x, world_motion_y;
214 GdkEvent * generated=new GdkEvent();
215 generated->motion.x=e->motion.x;
216 generated->motion.y=e->motion.y;
217 generated->type=GDK_MOTION_NOTIFY;
218 moveEventHandler(generated);
222 //finalize the new node
223 case GDK_BUTTON_RELEASE:
227 //Its appropriate color is given by update.
228 //*active_item << Gnome::Canvas::Properties::fill_color("blue");
232 //In this case the given color has to be overwritten, because the noe covers an other item.
233 *active_item << Gnome::Canvas::Properties::fill_color("lightblue");
245 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
249 case GDK_BUTTON_PRESS:
250 //in edge creation right button has special meaning
251 if(e->button.button!=3)
253 //there is not yet selected node
254 if(active_node==INVALID)
256 //we mark the location of the event to be able to calculate parameters of dragging
258 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
260 active_item=(get_item_at(clicked_x, clicked_y));
262 for (NodeIt i(g); i!=INVALID; ++i)
264 if(nodesmap[i]==active_item)
269 //the clicked item is really a node
270 if(active_node!=INVALID)
272 *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
275 //clicked item was not a node. It could be e.g. edge.
281 //we only have to do sg. if the mouse button
282 // is pressed already once AND the click was
283 // on a node that was found in the set of
284 //nodes, and now we only search for the second
288 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
289 target_item=(get_item_at(clicked_x, clicked_y));
290 Graph::NodeIt target_node=INVALID;
291 for (NodeIt i(g); i!=INVALID; ++i)
293 if(nodesmap[i]==target_item)
298 //the clicked item is a node, the edge can be drawn
299 if(target_node!=INVALID)
301 if(target_node!=active_node)
303 *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
306 active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
308 //initiating values corresponding to new edge in maps
309 mapstorage.initMapsForEdge(active_edge);
311 //calculating coordinates of new edge
312 Gnome::Canvas::Points coos;
313 double x1, x2, y1, y2;
315 active_item->get_bounds(x1, y1, x2, y2);
316 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
318 target_item->get_bounds(x1, y1, x2, y2);
319 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
322 edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos, *this);
323 *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
324 edgesmap[active_edge]->property_width_pixels().set_value(10);
326 //redraw nodes to blank terminations of the new edge
327 target_item->raise_to_top();
328 active_item->raise_to_top();
330 //initializing edge-text as well, to empty string
331 xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
332 text_pos+=(xy<double>(10,10));
334 edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
335 edgetextmap[active_edge]->property_fill_color().set_value("darkgreen");
337 //updating its properties
338 mapwin->updateEdge(active_edge);
343 std::cout << "Loop edge is not yet implemented!" << std::endl;
346 //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
354 case GDK_BUTTON_RELEASE:
356 //we clear settings in two cases
357 //1: the edge is ready (target_item has valid value)
358 //2: the edge creation is cancelled with right button
359 if((target_item)||(e->button.button==3))
363 *active_item << Gnome::Canvas::Properties::fill_color("blue");
368 *target_item << Gnome::Canvas::Properties::fill_color("blue");
381 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
385 case GDK_BUTTON_PRESS:
386 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
387 active_item=(get_item_at(clicked_x, clicked_y));
390 for (NodeIt i(g); i!=INVALID; ++i)
392 if(nodesmap[i]==active_item)
397 if(active_node==INVALID)
399 for (EdgeIt i(g); i!=INVALID; ++i)
401 if(edgesmap[i]==active_item)
409 *active_item << Gnome::Canvas::Properties::fill_color("red");
413 case GDK_BUTTON_RELEASE:
414 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
417 if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
419 if(active_node!=INVALID)
422 //collecting edges to delete
424 std::set<Graph::Edge> edges_to_delete;
426 g.firstOut(e,active_node);
427 for(;e!=INVALID;g.nextOut(e))
429 edges_to_delete.insert(e);
432 g.firstIn(e,active_node);
433 for(;e!=INVALID;g.nextIn(e))
435 edges_to_delete.insert(e);
438 //deleting collected edges
439 for(std::set<Graph::Edge>::iterator edge_set_it=edges_to_delete.begin();edge_set_it!=edges_to_delete.end();edge_set_it++)
441 deleteItem(*edge_set_it);
443 deleteItem(active_node);
445 //a simple edge was chosen
448 deleteItem(active_edge);
451 //pointer was moved, deletion is cancelled
454 if(active_node!=INVALID)
456 *active_item << Gnome::Canvas::Properties::fill_color("blue");
460 *active_item << Gnome::Canvas::Properties::fill_color("green");
470 case GDK_MOTION_NOTIFY:
479 void GraphDisplayerCanvas::deleteItem(NodeIt node_to_delete)
481 delete(nodetextmap[node_to_delete]);
482 delete(nodesmap[node_to_delete]);
483 g.erase(node_to_delete);
486 void GraphDisplayerCanvas::deleteItem(EdgeIt edge_to_delete)
488 delete(edgetextmap[edge_to_delete]);
489 delete(edgesmap[edge_to_delete]);
490 g.erase(edge_to_delete);
493 void GraphDisplayerCanvas::deleteItem(Graph::Edge edge_to_delete)
495 delete(edgetextmap[edge_to_delete]);
496 delete(edgesmap[edge_to_delete]);
497 g.erase(edge_to_delete);
500 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
502 new_place+=(xy<double>(10,10));
503 edgetextmap[active_edge]->property_x().set_value(new_place.x);
504 edgetextmap[active_edge]->property_y().set_value(new_place.y);
507 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
511 if(active_edge!=INVALID)
513 std::cout << "ERROR!!!! Valid edge found!" << std::endl;
517 for (EdgeIt i(g); i!=INVALID; ++i)
519 if(edgesmap[i]==active_bre)
528 if(active_edge!=INVALID)
534 std::cout << "ERROR!!!! Invalid edge found!" << std::endl;