NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
1 #include "graph_displayer_canvas.h"
5 bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
7 Gnome::Canvas::CanvasAA::on_expose_event(event);
13 void GraphDisplayerCanvas::changeEditorialTool(int newtool)
15 if(actual_tool!=newtool)
18 actual_handler.disconnect();
24 GdkEvent * generated=new GdkEvent();
25 generated->type=GDK_BUTTON_RELEASE;
26 generated->button.button=3;
27 createEdgeEventHandler(generated);
31 //has to do the same thing as in the case of NODE_MAP_EDIT
51 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::moveEventHandler), false);
55 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createNodeEventHandler), false);
59 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::createEdgeEventHandler), false);
63 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
68 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
72 actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
81 int GraphDisplayerCanvas::getActualTool()
86 bool GraphDisplayerCanvas::moveEventHandler(GdkEvent* e)
88 static Gnome::Canvas::Text *coord_text = 0;
91 case GDK_BUTTON_PRESS:
92 //we mark the location of the event to be able to calculate parameters of dragging
93 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
95 active_item=(get_item_at(clicked_x, clicked_y));
97 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
99 if(nodesmap[i]==active_item)
104 switch(e->button.button)
114 case GDK_BUTTON_RELEASE:
124 case GDK_MOTION_NOTIFY:
125 //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
126 if(active_node!=INVALID)
128 mapstorage.modified = true;
130 //new coordinates will be the old values,
131 //because the item will be moved to the
132 //new coordinate therefore the new movement
133 //has to be calculated from here
137 window_to_world (e->motion.x, e->motion.y, new_x, new_y);
139 double dx=new_x-clicked_x;
140 double dy=new_y-clicked_y;
142 //repositioning node and its text
143 active_item->move(dx, dy);
144 nodetextmap[active_node]->move(dx, dy);
146 // the new coordinates of the centre of the node
147 double coord_x = new_x - (clicked_x - mapstorage.coords[active_node].x);
148 double coord_y = new_y - (clicked_y - mapstorage.coords[active_node].y);
153 // write back the new coordinates to the coords map
154 mapstorage.coords.set(active_node, xy<double>(coord_x, coord_y));
156 // reposition the coordinates text
157 std::ostringstream ostr;
159 mapstorage.coords[active_node].x << ", " <<
160 mapstorage.coords[active_node].y << ")";
162 (nodesmap[active_node]->property_x2().get_value() -
163 nodesmap[active_node]->property_x1().get_value()) / 2.0;
166 coord_text->property_text().set_value(ostr.str());
167 coord_text->property_x().set_value(mapstorage.coords[active_node].x +
169 coord_text->property_y().set_value(mapstorage.coords[active_node].y -
174 coord_text = new Gnome::Canvas::Text(
176 mapstorage.coords[active_node].x + radius,
177 mapstorage.coords[active_node].y - radius,
179 coord_text->property_fill_color().set_value("black");
180 coord_text->property_anchor().set_value(Gtk::ANCHOR_SOUTH_WEST);
183 //all the edges connected to the moved point has to be redrawn
184 for(OutEdgeIt ei(mapstorage.graph,active_node);ei!=INVALID;++ei)
186 Gnome::Canvas::Points coos;
187 double x1, x2, y1, y2;
189 nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
190 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
192 nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
193 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
197 edgesmap[ei]->setPoints(coos);
201 edgesmap[ei]->setPoints(coos,true);
204 //reposition of edgetext
205 xy<double> text_pos=edgesmap[ei]->getArrowPos();
206 text_pos+=(xy<double>(10,10));
207 edgetextmap[ei]->property_x().set_value(text_pos.x);
208 edgetextmap[ei]->property_y().set_value(text_pos.y);
211 for(InEdgeIt ei(mapstorage.graph,active_node);ei!=INVALID;++ei)
213 Gnome::Canvas::Points coos;
214 double x1, x2, y1, y2;
216 nodesmap[mapstorage.graph.source(ei)]->get_bounds(x1, y1, x2, y2);
217 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
219 nodesmap[mapstorage.graph.target(ei)]->get_bounds(x1, y1, x2, y2);
220 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
224 edgesmap[ei]->setPoints(coos);
228 edgesmap[ei]->setPoints(coos,true);
231 xy<double> text_pos=edgesmap[ei]->getArrowPos();
232 text_pos+=(xy<double>(10,10));
233 edgetextmap[ei]->property_x().set_value(text_pos.x);
234 edgetextmap[ei]->property_y().set_value(text_pos.y);
243 bool GraphDisplayerCanvas::createNodeEventHandler(GdkEvent* e)
248 case GDK_MOTION_NOTIFY:
250 GdkEvent * generated=new GdkEvent();
251 generated->motion.x=e->motion.x;
252 generated->motion.y=e->motion.y;
253 generated->type=GDK_MOTION_NOTIFY;
254 moveEventHandler(generated);
258 case GDK_BUTTON_RELEASE:
259 mapstorage.modified = true;
263 active_node=mapstorage.graph.addNode();
265 //initiating values corresponding to new node in maps
267 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
269 // update coordinates
270 mapstorage.coords.set(active_node, xy<double>(clicked_x, clicked_y));
272 // update all other maps
273 for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
274 mapstorage.nodemap_storage.begin(); it !=
275 mapstorage.nodemap_storage.end(); ++it)
277 if ((it->first != "coordinates_x") &&
278 (it->first != "coordinates_y"))
280 (*(it->second))[active_node] =
281 mapstorage.nodemap_default[it->first];
284 // increment the id map's default value
285 mapstorage.nodemap_default["id"] += 1.0;
287 nodesmap[active_node]=new Gnome::Canvas::Ellipse(displayed_graph,
288 clicked_x-20, clicked_y-20, clicked_x+20, clicked_y+20);
289 active_item=(Gnome::Canvas::Item *)(nodesmap[active_node]);
290 *(nodesmap[active_node]) <<
291 Gnome::Canvas::Properties::fill_color("blue");
292 *(nodesmap[active_node]) <<
293 Gnome::Canvas::Properties::outline_color("black");
294 active_item->raise_to_top();
296 (nodesmap[active_node])->show();
298 nodetextmap[active_node]=new Gnome::Canvas::Text(displayed_graph,
299 clicked_x+node_property_defaults[N_RADIUS]+5,
300 clicked_y+node_property_defaults[N_RADIUS]+5, "");
301 nodetextmap[active_node]->property_fill_color().set_value("darkblue");
302 nodetextmap[active_node]->raise_to_top();
304 mapwin.updateNode(active_node);
317 bool GraphDisplayerCanvas::createEdgeEventHandler(GdkEvent* e)
321 case GDK_BUTTON_PRESS:
322 //in edge creation right button has special meaning
323 if(e->button.button!=3)
325 //there is not yet selected node
326 if(active_node==INVALID)
328 //we mark the location of the event to be able to calculate parameters of dragging
330 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
332 active_item=(get_item_at(clicked_x, clicked_y));
334 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
336 if(nodesmap[i]==active_item)
341 //the clicked item is really a node
342 if(active_node!=INVALID)
344 *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
347 //clicked item was not a node. It could be e.g. edge.
353 //we only have to do sg. if the mouse button
354 // is pressed already once AND the click was
355 // on a node that was found in the set of
356 //nodes, and now we only search for the second
360 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
361 target_item=(get_item_at(clicked_x, clicked_y));
362 Node target_node=INVALID;
363 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
365 if(nodesmap[i]==target_item)
370 //the clicked item is a node, the edge can be drawn
371 if(target_node!=INVALID)
373 if(target_node!=active_node)
375 mapstorage.modified = true;
377 *(nodesmap[target_node]) <<
378 Gnome::Canvas::Properties::fill_color("red");
381 active_edge=mapstorage.graph.addEdge(active_node,
385 for (std::map<std::string,
386 Graph::EdgeMap<double>*>::const_iterator it =
387 mapstorage.edgemap_storage.begin(); it !=
388 mapstorage.edgemap_storage.end(); ++it)
390 (*(it->second))[active_edge] =
391 mapstorage.edgemap_default[it->first];
393 // increment the id map's default value
394 mapstorage.edgemap_default["id"] += 1.0;
396 //calculating coordinates of new edge
397 Gnome::Canvas::Points coos;
398 double x1, x2, y1, y2;
400 active_item->get_bounds(x1, y1, x2, y2);
401 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
403 target_item->get_bounds(x1, y1, x2, y2);
404 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
407 edgesmap[active_edge]=new BrokenEdge(displayed_graph, coos,
409 *(edgesmap[active_edge]) <<
410 Gnome::Canvas::Properties::fill_color("green");
411 edgesmap[active_edge]->property_width_pixels().set_value(10);
413 edgesmap[active_edge]->lower_to_bottom();
415 //initializing edge-text as well, to empty string
416 xy<double> text_pos=edgesmap[active_edge]->getArrowPos();
417 text_pos+=(xy<double>(10,10));
419 edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,
420 text_pos.x, text_pos.y, "");
421 edgetextmap[active_edge]->property_fill_color().set_value(
423 edgetextmap[active_edge]->raise_to_top();
425 //updating its properties
426 mapwin.updateEdge(active_edge);
431 std::cerr << "Loop edge is not yet implemented!" << std::endl;
434 //clicked item was not a node. it could be an e.g. edge. we do not
435 //deal with it furthermore.
443 case GDK_BUTTON_RELEASE:
445 //we clear settings in two cases
446 //1: the edge is ready (target_item has valid value)
447 //2: the edge creation is cancelled with right button
448 if((target_item)||(e->button.button==3))
452 *active_item << Gnome::Canvas::Properties::fill_color("blue");
457 *target_item << Gnome::Canvas::Properties::fill_color("blue");
470 bool GraphDisplayerCanvas::eraserEventHandler(GdkEvent* e)
474 case GDK_BUTTON_PRESS:
475 //finding the clicked items
476 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
477 active_item=(get_item_at(clicked_x, clicked_y));
481 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
483 if(nodesmap[i]==active_item)
489 if(active_node==INVALID)
491 for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
493 if(edgesmap[i]==active_item)
500 //recolor activated item
503 *active_item << Gnome::Canvas::Properties::fill_color("red");
507 case GDK_BUTTON_RELEASE:
508 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
511 //the cursor was not moved since pressing it
512 if( active_item == ( get_item_at (clicked_x, clicked_y) ) )
515 if(active_node!=INVALID)
517 mapstorage.modified = true;
519 std::set<Graph::Edge> edges_to_delete;
521 for(OutEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
523 edges_to_delete.insert(e);
526 for(InEdgeIt e(mapstorage.graph,active_node);e!=INVALID;++e)
528 edges_to_delete.insert(e);
531 //deleting collected edges
532 for(std::set<Graph::Edge>::iterator
533 edge_set_it=edges_to_delete.begin();
534 edge_set_it!=edges_to_delete.end();
537 deleteItem(*edge_set_it);
539 deleteItem(active_node);
541 //a simple edge was chosen
544 deleteItem(active_edge);
547 //pointer was moved, deletion is cancelled
550 if(active_node!=INVALID)
552 *active_item << Gnome::Canvas::Properties::fill_color("blue");
556 *active_item << Gnome::Canvas::Properties::fill_color("green");
566 case GDK_MOTION_NOTIFY:
575 bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
577 if(actual_tool==EDGE_MAP_EDIT)
581 case GDK_BUTTON_PRESS:
583 //for determine, whether it was an edge
584 Edge clicked_edge=INVALID;
586 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
587 active_item=(get_item_at(clicked_x, clicked_y));
589 //find the activated item between texts
590 for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
592 //at the same time only one can be active
593 if(edgetextmap[i]==active_item)
599 //if it was not between texts, search for it between edges
600 if(clicked_edge==INVALID)
602 for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
604 //at the same time only one can be active
605 if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
612 //if it was really an edge...
613 if(clicked_edge!=INVALID)
615 // the id map is not editable
616 if (edgemap_to_edit == "id") return 0;
618 //and there is activated map
619 if(edgetextmap[clicked_edge]->property_text().get_value()!="")
621 //activate the general variable for it
622 active_edge=clicked_edge;
625 Gtk::Dialog dialog("Edit value", *parentwin, true);
626 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
627 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
628 Gtk::VBox* vbox = dialog.get_vbox();
630 (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge],
634 //TODO: find out why doesn't it work with
635 //numeric_limits<double>::min/max
636 Gtk::SpinButton spin(adj);
637 spin.set_numeric(true);
641 switch (dialog.run())
643 case Gtk::RESPONSE_NONE:
644 case Gtk::RESPONSE_CANCEL:
646 case Gtk::RESPONSE_ACCEPT:
647 double new_value = spin.get_value();
648 (*mapstorage.edgemap_storage[edgemap_to_edit])[active_edge] =
650 std::ostringstream ostr;
652 edgetextmap[active_edge]->property_text().set_value(
654 //mapwin.updateEdge(active_edge);
655 mapwin.updateEdge(Edge(INVALID));
668 bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
670 if(actual_tool==NODE_MAP_EDIT)
674 case GDK_BUTTON_PRESS:
676 //for determine, whether it was a node
677 Node clicked_node=INVALID;
679 window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
680 active_item=(get_item_at(clicked_x, clicked_y));
682 //find the activated item between texts
683 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
685 //at the same time only one can be active
686 if(nodetextmap[i]==active_item)
692 //if there was not, search for it between nodes
693 if(clicked_node==INVALID)
695 for (NodeIt i(mapstorage.graph); i!=INVALID; ++i)
697 //at the same time only one can be active
698 if(nodesmap[i]==active_item)
705 //if it was really a node...
706 if(clicked_node!=INVALID)
708 // the id map is not editable
709 if (nodemap_to_edit == "id") return 0;
711 //and there is activated map
712 if(nodetextmap[clicked_node]->property_text().get_value()!="")
714 //activate the general variable for it
715 active_node=clicked_node;
718 Gtk::Dialog dialog("Edit value", *parentwin, true);
719 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
720 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
721 Gtk::VBox* vbox = dialog.get_vbox();
723 (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node],
727 //TODO: find out why doesn't it work with
728 //numeric_limits<double>::min/max
729 Gtk::SpinButton spin(adj);
730 spin.set_numeric(true);
734 switch (dialog.run())
736 case Gtk::RESPONSE_NONE:
737 case Gtk::RESPONSE_CANCEL:
739 case Gtk::RESPONSE_ACCEPT:
740 double new_value = spin.get_value();
741 (*mapstorage.nodemap_storage[nodemap_to_edit])[active_node] =
743 std::ostringstream ostr;
745 nodetextmap[active_node]->property_text().set_value(
747 //mapwin.updateNode(active_node);
748 mapwin.updateNode(Node(INVALID));
761 void GraphDisplayerCanvas::deleteItem(Node node_to_delete)
763 delete(nodetextmap[node_to_delete]);
764 delete(nodesmap[node_to_delete]);
765 mapstorage.graph.erase(node_to_delete);
768 void GraphDisplayerCanvas::deleteItem(Edge edge_to_delete)
770 delete(edgetextmap[edge_to_delete]);
771 delete(edgesmap[edge_to_delete]);
772 mapstorage.graph.erase(edge_to_delete);
775 void GraphDisplayerCanvas::textReposition(xy<double> new_place)
777 new_place+=(xy<double>(10,10));
778 edgetextmap[forming_edge]->property_x().set_value(new_place.x);
779 edgetextmap[forming_edge]->property_y().set_value(new_place.y);
782 void GraphDisplayerCanvas::toggleEdgeActivity(BrokenEdge* active_bre, bool on)
786 if(forming_edge!=INVALID)
788 std::cerr << "ERROR!!!! Valid edge found!" << std::endl;
792 for (EdgeIt i(mapstorage.graph); i!=INVALID; ++i)
794 if(edgesmap[i]==active_bre)
803 if(forming_edge!=INVALID)
805 forming_edge=INVALID;
809 std::cerr << "ERROR!!!! Invalid edge found!" << std::endl;
815 int GraphDisplayerCanvas::addNewEdgeMap(double default_value, std::string mapname)
818 Graph::EdgeMap<double> * emptr=new Graph::EdgeMap<double> (mapstorage.graph, default_value);
820 //if addition was not successful addEdgeMap returns one.
821 //cause can be that there is already a map named like the new one
822 if(mapstorage.addEdgeMap(mapname,emptr, default_value))
828 //add it to the list of the displayable maps
829 mapwin.registerNewEdgeMap(mapname);
832 changeEdgeText(mapname);
837 int GraphDisplayerCanvas::addNewNodeMap(double default_value, std::string mapname)
840 Graph::NodeMap<double> * emptr=new Graph::NodeMap<double> (mapstorage.graph,default_value);
842 //if addition was not successful addNodeMap returns one.
843 //cause can be that there is already a map named like the new one
844 if(mapstorage.addNodeMap(mapname,emptr, default_value))
849 //add it to the list of the displayable maps
850 mapwin.registerNewNodeMap(mapname);
853 changeNodeText(mapname);