1 // This example was started by Guillaume Laurent.
2 // It has become a place to dump code that tests parts of the
3 // gnomemm canvas code. Little thought has been given to the
4 // actual on-screen output.
6 #include <libgnomecanvasmm.h>
7 #include <libgnomecanvasmm/polygon.h>
12 #include <lemon/list_graph.h>
13 #include <lemon/graph_reader.h>
14 #include <lemon/graph_writer.h>
15 #include <lemon/graph_utils.h>
16 #include <lemon/maps.h>
17 #include <lemon/error.h>
20 using namespace lemon;
22 typedef xy<double> Coordinates;
23 typedef ListGraph Graph;
24 typedef Graph::NodeMap<Coordinates> CoordinatesMap;
25 typedef Graph::Node Node;
26 typedef Graph::EdgeIt EdgeIt;
27 typedef Graph::NodeIt NodeIt;
29 class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA
31 typedef Gnome::Canvas::CanvasAA Parent;
34 GraphDisplayerCanvas(Graph &, CoordinatesMap &);
35 virtual ~GraphDisplayerCanvas();
39 ///Event handler function that handles dragging nodes of displayed_graph
40 bool event_handler(GdkEvent* e, Node n);
42 ///The graph, on which we work
44 ///Map of nodes of planefigure
45 Graph::NodeMap<Gnome::Canvas::Ellipse *> nodesmap;
46 ///Map of edges of planefigure
47 Graph::EdgeMap<Gnome::Canvas::Line *> edgesmap;
48 ///Group of graphical elements of displayed_graph
49 Gnome::Canvas::Group displayed_graph;
51 ///Indicates whether the button of mouse is pressed or not
54 ///At this location was the mousebutton pressed.
55 ///It helps to calculate the distance of dragging.
56 double clicked_x, clicked_y;
58 ///Remembers which Gnome::Canvas::Item was pressed.
59 ///this variable is needed, because
60 ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault
61 ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution
62 Gnome::Canvas::Item * active_item;
68 ///This function moves only one node of displayed_graph,
69 ///but recalculate the location of weight point,
70 ///and also redraw the sides of the planefigure.
71 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
75 case GDK_BUTTON_PRESS:
76 clicked_x=e->button.x;
77 clicked_y=e->button.y;
78 active_item=(get_item_at(e->button.x, e->button.y));
81 case GDK_BUTTON_RELEASE:
85 case GDK_MOTION_NOTIFY:
88 double dx=e->motion.x-clicked_x;
89 double dy=e->motion.y-clicked_y;
90 active_item->move(dx, dy);
91 clicked_x=e->motion.x;
92 clicked_y=e->motion.y;
97 for(;e!=INVALID;g.nextOut(e))
99 Gnome::Canvas::Points coos;
100 double x1, x2, y1, y2;
102 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
103 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
105 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
106 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
108 edgesmap[e]->property_points().set_value(coos);
112 for(;e!=INVALID;g.nextIn(e))
114 Gnome::Canvas::Points coos;
115 double x1, x2, y1, y2;
117 nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
118 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
120 nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
121 coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
123 edgesmap[e]->property_points().set_value(coos);
131 GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm):g(gr),nodesmap(g),edgesmap(g),displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL)
133 for (EdgeIt i(g); i!=INVALID; ++i)
135 Gnome::Canvas::Points coos;
136 coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
137 coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
138 edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos);
139 *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
140 edgesmap[i]->property_width_pixels().set_value(10);
142 for (NodeIt i(g); i!=INVALID; ++i)
144 nodesmap[i]=new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
145 *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
146 *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
147 (nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
152 GraphDisplayerCanvas::~GraphDisplayerCanvas()
154 Graph::NodeMap <int> id(g);
155 Graph::NodeMap <double> xc(g);
156 Graph::NodeMap <double> yc(g);
160 for (NodeIt i(g); i!=INVALID; ++i)
163 nodesmap[i]->get_bounds(x1, y1, x2, y2);
170 GraphWriter<Graph> writer(std::cout,g);
172 writer.addNodeMap("id", id);
173 writer.addNodeMap("coordinates_x", xc);
174 writer.addNodeMap("coordinates_y", yc);
180 class MainWin : public Gtk::Window
183 MainWin(const std::string& title, Graph &, CoordinatesMap &);
187 GraphDisplayerCanvas gd_canvas;
190 MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm)
194 set_default_size(900,600);
200 ///This class is responsible for being able
201 ///to read xy datastructure from file. It is
202 ///based on BaseMap. The set method sets the
203 ///appropriate value in the final xy NodeMap
204 ///that was given to the constructor.
205 class CoordReaderMap: public MapBase <Node, double>
211 CoordReaderMap(char xory, CoordinatesMap & coordmap);
212 void set(Node node, double coord);
215 ///The constructor expects for an xy NodeMap,
216 ///and we have to tell it, for which value
217 ///of the xy vector is responsible the actual
219 CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap)
228 throw UninitializedParameter() ;
232 ///set method sets the appropriate value in the
233 ///xy type NodeMap that is under construction
234 void CoordReaderMap::set(Node node, double coord)
245 throw UninitializedParameter() ;
251 int main(int argc, char *argv[])
255 std::cerr << "USAGE: gd <input filename.lgf>" << endl;
259 Coordinates coosvector;
263 CoordinatesMap cm(g);
264 Graph::EdgeMap<double> cap(g);
266 //we create one object to read x coordinates
267 //and one to read y coordinate of nodes and write them to cm NodeMap.
268 CoordReaderMap xreader('x',cm);
269 CoordReaderMap yreader('y',cm);
271 std::ifstream is(argv[1]);
273 GraphReader<Graph> reader(is, g);
274 reader.addNodeMap("coordinates_x", xreader);
275 reader.addNodeMap("coordinates_y", yreader);
278 Gnome::Canvas::init();
279 Gtk::Main app(argc, argv);
281 MainWin mainwin("Displayed Graph", g, cm);