hegyi@1289
|
1 |
// This example was started by Guillaume Laurent.
|
hegyi@1289
|
2 |
// It has become a place to dump code that tests parts of the
|
hegyi@1289
|
3 |
// gnomemm canvas code. Little thought has been given to the
|
hegyi@1289
|
4 |
// actual on-screen output.
|
hegyi@1289
|
5 |
|
hegyi@1289
|
6 |
#include <libgnomecanvasmm.h>
|
hegyi@1289
|
7 |
#include <libgnomecanvasmm/polygon.h>
|
hegyi@1289
|
8 |
|
hegyi@1289
|
9 |
#include <fstream>
|
hegyi@1289
|
10 |
#include <iostream>
|
hegyi@1289
|
11 |
|
hegyi@1289
|
12 |
#include <lemon/list_graph.h>
|
hegyi@1289
|
13 |
#include <lemon/graph_reader.h>
|
hegyi@1301
|
14 |
#include <lemon/graph_writer.h>
|
hegyi@1289
|
15 |
#include <lemon/graph_utils.h>
|
hegyi@1289
|
16 |
#include <lemon/maps.h>
|
hegyi@1289
|
17 |
#include <lemon/error.h>
|
hegyi@1289
|
18 |
#include <lemon/xy.h>
|
hegyi@1289
|
19 |
|
hegyi@1289
|
20 |
using namespace lemon;
|
hegyi@1289
|
21 |
|
hegyi@1289
|
22 |
typedef xy<double> Coordinates;
|
hegyi@1289
|
23 |
typedef ListGraph Graph;
|
hegyi@1289
|
24 |
typedef Graph::NodeMap<Coordinates> CoordinatesMap;
|
hegyi@1289
|
25 |
typedef Graph::Node Node;
|
hegyi@1289
|
26 |
typedef Graph::EdgeIt EdgeIt;
|
hegyi@1289
|
27 |
typedef Graph::NodeIt NodeIt;
|
hegyi@1289
|
28 |
|
hegyi@1289
|
29 |
class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA
|
hegyi@1289
|
30 |
{
|
hegyi@1289
|
31 |
typedef Gnome::Canvas::CanvasAA Parent;
|
hegyi@1289
|
32 |
|
hegyi@1289
|
33 |
public:
|
hegyi@1289
|
34 |
GraphDisplayerCanvas(Graph &, CoordinatesMap &);
|
hegyi@1289
|
35 |
virtual ~GraphDisplayerCanvas();
|
hegyi@1289
|
36 |
|
hegyi@1289
|
37 |
private:
|
hegyi@1289
|
38 |
|
hegyi@1289
|
39 |
///Event handler function that handles dragging nodes of displayed_graph
|
hegyi@1301
|
40 |
bool event_handler(GdkEvent* e, Node n);
|
hegyi@1289
|
41 |
|
hegyi@1301
|
42 |
///The graph, on which we work
|
hegyi@1301
|
43 |
Graph g;
|
hegyi@1301
|
44 |
///Map of nodes of planefigure
|
hegyi@1301
|
45 |
Graph::NodeMap<Gnome::Canvas::Ellipse *> nodesmap;
|
hegyi@1301
|
46 |
///Map of edges of planefigure
|
hegyi@1301
|
47 |
Graph::EdgeMap<Gnome::Canvas::Line *> edgesmap;
|
hegyi@1289
|
48 |
///Group of graphical elements of displayed_graph
|
hegyi@1289
|
49 |
Gnome::Canvas::Group displayed_graph;
|
hegyi@1289
|
50 |
|
hegyi@1289
|
51 |
///Indicates whether the button of mouse is pressed or not
|
hegyi@1289
|
52 |
bool isbutton;
|
hegyi@1289
|
53 |
|
hegyi@1289
|
54 |
///At this location was the mousebutton pressed.
|
hegyi@1289
|
55 |
///It helps to calculate the distance of dragging.
|
hegyi@1289
|
56 |
double clicked_x, clicked_y;
|
hegyi@1289
|
57 |
|
hegyi@1289
|
58 |
///Remembers which Gnome::Canvas::Item was pressed.
|
hegyi@1289
|
59 |
///this variable is needed, because
|
hegyi@1289
|
60 |
///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault
|
hegyi@1289
|
61 |
///2. we would like to handle only ony item per movement, therefore quering it is not a working solution
|
hegyi@1289
|
62 |
Gnome::Canvas::Item * active_item;
|
hegyi@1289
|
63 |
|
hegyi@1289
|
64 |
|
hegyi@1289
|
65 |
};
|
hegyi@1289
|
66 |
|
hegyi@1289
|
67 |
|
hegyi@1289
|
68 |
///This function moves only one node of displayed_graph,
|
hegyi@1289
|
69 |
///but recalculate the location of weight point,
|
hegyi@1289
|
70 |
///and also redraw the sides of the planefigure.
|
hegyi@1301
|
71 |
bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
|
hegyi@1289
|
72 |
{
|
hegyi@1289
|
73 |
switch(e->type)
|
hegyi@1289
|
74 |
{
|
hegyi@1289
|
75 |
case GDK_BUTTON_PRESS:
|
hegyi@1289
|
76 |
clicked_x=e->button.x;
|
hegyi@1289
|
77 |
clicked_y=e->button.y;
|
hegyi@1289
|
78 |
active_item=(get_item_at(e->button.x, e->button.y));
|
hegyi@1289
|
79 |
isbutton=true;
|
hegyi@1289
|
80 |
break;
|
hegyi@1289
|
81 |
case GDK_BUTTON_RELEASE:
|
hegyi@1289
|
82 |
isbutton=false;
|
hegyi@1289
|
83 |
active_item=NULL;
|
hegyi@1289
|
84 |
break;
|
hegyi@1289
|
85 |
case GDK_MOTION_NOTIFY:
|
hegyi@1289
|
86 |
if(isbutton)
|
hegyi@1289
|
87 |
{
|
hegyi@1289
|
88 |
double dx=e->motion.x-clicked_x;
|
hegyi@1289
|
89 |
double dy=e->motion.y-clicked_y;
|
hegyi@1289
|
90 |
active_item->move(dx, dy);
|
hegyi@1289
|
91 |
clicked_x=e->motion.x;
|
hegyi@1289
|
92 |
clicked_y=e->motion.y;
|
hegyi@1301
|
93 |
|
hegyi@1301
|
94 |
EdgeIt e;
|
hegyi@1301
|
95 |
|
hegyi@1301
|
96 |
g.firstOut(e,n);
|
hegyi@1301
|
97 |
for(;e!=INVALID;g.nextOut(e))
|
hegyi@1301
|
98 |
{
|
hegyi@1301
|
99 |
Gnome::Canvas::Points coos;
|
hegyi@1301
|
100 |
double x1, x2, y1, y2;
|
hegyi@1301
|
101 |
|
hegyi@1301
|
102 |
nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
|
hegyi@1301
|
103 |
coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
|
hegyi@1301
|
104 |
|
hegyi@1301
|
105 |
nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
|
hegyi@1301
|
106 |
coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
|
hegyi@1301
|
107 |
|
hegyi@1301
|
108 |
edgesmap[e]->property_points().set_value(coos);
|
hegyi@1301
|
109 |
}
|
hegyi@1301
|
110 |
|
hegyi@1301
|
111 |
g.firstIn(e,n);
|
hegyi@1301
|
112 |
for(;e!=INVALID;g.nextIn(e))
|
hegyi@1301
|
113 |
{
|
hegyi@1301
|
114 |
Gnome::Canvas::Points coos;
|
hegyi@1301
|
115 |
double x1, x2, y1, y2;
|
hegyi@1301
|
116 |
|
hegyi@1301
|
117 |
nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
|
hegyi@1301
|
118 |
coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
|
hegyi@1301
|
119 |
|
hegyi@1301
|
120 |
nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
|
hegyi@1301
|
121 |
coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
|
hegyi@1301
|
122 |
|
hegyi@1301
|
123 |
edgesmap[e]->property_points().set_value(coos);
|
hegyi@1301
|
124 |
}
|
hegyi@1289
|
125 |
}
|
hegyi@1289
|
126 |
default: break;
|
hegyi@1289
|
127 |
}
|
hegyi@1289
|
128 |
return true;
|
hegyi@1289
|
129 |
}
|
hegyi@1289
|
130 |
|
hegyi@1301
|
131 |
GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm):g(gr),nodesmap(g),edgesmap(g),displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL)
|
hegyi@1289
|
132 |
{
|
hegyi@1301
|
133 |
for (EdgeIt i(g); i!=INVALID; ++i)
|
hegyi@1301
|
134 |
{
|
hegyi@1301
|
135 |
Gnome::Canvas::Points coos;
|
hegyi@1301
|
136 |
coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
|
hegyi@1301
|
137 |
coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
|
hegyi@1301
|
138 |
edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos);
|
hegyi@1301
|
139 |
*(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
|
hegyi@1301
|
140 |
edgesmap[i]->property_width_pixels().set_value(10);
|
hegyi@1301
|
141 |
}
|
hegyi@1289
|
142 |
for (NodeIt i(g); i!=INVALID; ++i)
|
hegyi@1289
|
143 |
{
|
hegyi@1301
|
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);
|
hegyi@1301
|
145 |
*(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
|
hegyi@1301
|
146 |
*(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
|
hegyi@1301
|
147 |
(nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
|
hegyi@1289
|
148 |
}
|
hegyi@1289
|
149 |
|
hegyi@1289
|
150 |
}
|
hegyi@1289
|
151 |
|
hegyi@1289
|
152 |
GraphDisplayerCanvas::~GraphDisplayerCanvas()
|
hegyi@1289
|
153 |
{
|
hegyi@1301
|
154 |
Graph::NodeMap <int> id(g);
|
hegyi@1301
|
155 |
Graph::NodeMap <double> xc(g);
|
hegyi@1301
|
156 |
Graph::NodeMap <double> yc(g);
|
hegyi@1301
|
157 |
|
hegyi@1301
|
158 |
int j=1;
|
hegyi@1301
|
159 |
|
hegyi@1301
|
160 |
for (NodeIt i(g); i!=INVALID; ++i)
|
hegyi@1301
|
161 |
{
|
hegyi@1301
|
162 |
double x1,y1,x2,y2;
|
hegyi@1301
|
163 |
nodesmap[i]->get_bounds(x1, y1, x2, y2);
|
hegyi@1301
|
164 |
|
hegyi@1301
|
165 |
id[i]=j++;
|
hegyi@1301
|
166 |
xc[i]=(x1+x2)/2;
|
hegyi@1301
|
167 |
yc[i]=(y1+y2)/2;
|
hegyi@1301
|
168 |
}
|
hegyi@1301
|
169 |
|
hegyi@1301
|
170 |
GraphWriter<Graph> writer(std::cout,g);
|
hegyi@1301
|
171 |
|
hegyi@1301
|
172 |
writer.addNodeMap("id", id);
|
hegyi@1301
|
173 |
writer.addNodeMap("coordinates_x", xc);
|
hegyi@1301
|
174 |
writer.addNodeMap("coordinates_y", yc);
|
hegyi@1301
|
175 |
writer.run();
|
hegyi@1289
|
176 |
}
|
hegyi@1289
|
177 |
|
hegyi@1301
|
178 |
|
hegyi@1289
|
179 |
//MainWin:
|
hegyi@1289
|
180 |
class MainWin : public Gtk::Window
|
hegyi@1289
|
181 |
{
|
hegyi@1289
|
182 |
public:
|
hegyi@1289
|
183 |
MainWin(const std::string& title, Graph &, CoordinatesMap &);
|
hegyi@1289
|
184 |
|
hegyi@1289
|
185 |
protected:
|
hegyi@1289
|
186 |
//Member widgets:
|
hegyi@1289
|
187 |
GraphDisplayerCanvas gd_canvas;
|
hegyi@1289
|
188 |
};
|
hegyi@1289
|
189 |
|
hegyi@1289
|
190 |
MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm)
|
hegyi@1289
|
191 |
{
|
hegyi@1289
|
192 |
set_title (title);
|
hegyi@1289
|
193 |
add(gd_canvas);
|
hegyi@1289
|
194 |
set_default_size(900,600);
|
hegyi@1289
|
195 |
|
hegyi@1289
|
196 |
show_all();
|
hegyi@1289
|
197 |
}
|
hegyi@1289
|
198 |
|
hegyi@1289
|
199 |
|
hegyi@1289
|
200 |
///This class is responsible for being able
|
hegyi@1289
|
201 |
///to read xy datastructure from file. It is
|
hegyi@1289
|
202 |
///based on BaseMap. The set method sets the
|
hegyi@1289
|
203 |
///appropriate value in the final xy NodeMap
|
hegyi@1289
|
204 |
///that was given to the constructor.
|
hegyi@1289
|
205 |
class CoordReaderMap: public MapBase <Node, double>
|
hegyi@1289
|
206 |
{
|
hegyi@1289
|
207 |
CoordinatesMap & cm;
|
hegyi@1289
|
208 |
char xoy;
|
hegyi@1289
|
209 |
|
hegyi@1289
|
210 |
public:
|
hegyi@1289
|
211 |
CoordReaderMap(char xory, CoordinatesMap & coordmap);
|
hegyi@1289
|
212 |
void set(Node node, double coord);
|
hegyi@1289
|
213 |
};
|
hegyi@1289
|
214 |
|
hegyi@1289
|
215 |
///The constructor expects for an xy NodeMap,
|
hegyi@1289
|
216 |
///and we have to tell it, for which value
|
hegyi@1289
|
217 |
///of the xy vector is responsible the actual
|
hegyi@1289
|
218 |
///copy.
|
hegyi@1289
|
219 |
CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap)
|
hegyi@1289
|
220 |
{
|
hegyi@1289
|
221 |
switch(xory)
|
hegyi@1289
|
222 |
{
|
hegyi@1289
|
223 |
case 'x':
|
hegyi@1289
|
224 |
case 'y':
|
hegyi@1289
|
225 |
xoy=xory;
|
hegyi@1289
|
226 |
break;
|
hegyi@1289
|
227 |
default:
|
hegyi@1289
|
228 |
throw UninitializedParameter() ;
|
hegyi@1289
|
229 |
}
|
hegyi@1289
|
230 |
}
|
hegyi@1289
|
231 |
|
hegyi@1289
|
232 |
///set method sets the appropriate value in the
|
hegyi@1289
|
233 |
///xy type NodeMap that is under construction
|
hegyi@1289
|
234 |
void CoordReaderMap::set(Node node, double coord)
|
hegyi@1289
|
235 |
{
|
hegyi@1289
|
236 |
switch(xoy)
|
hegyi@1289
|
237 |
{
|
hegyi@1289
|
238 |
case 'x':
|
hegyi@1289
|
239 |
cm[node].x=coord;
|
hegyi@1289
|
240 |
break;
|
hegyi@1289
|
241 |
case 'y':
|
hegyi@1289
|
242 |
cm[node].y=coord;
|
hegyi@1289
|
243 |
break;
|
hegyi@1289
|
244 |
default:
|
hegyi@1289
|
245 |
throw UninitializedParameter() ;
|
hegyi@1289
|
246 |
}
|
hegyi@1289
|
247 |
}
|
hegyi@1289
|
248 |
|
hegyi@1289
|
249 |
//main():
|
hegyi@1289
|
250 |
|
hegyi@1289
|
251 |
int main(int argc, char *argv[])
|
hegyi@1289
|
252 |
{
|
hegyi@1290
|
253 |
if(argc<2)
|
hegyi@1290
|
254 |
{
|
hegyi@1290
|
255 |
std::cerr << "USAGE: gd <input filename.lgf>" << endl;
|
hegyi@1290
|
256 |
return 0;
|
hegyi@1290
|
257 |
}
|
hegyi@1289
|
258 |
|
hegyi@1289
|
259 |
Coordinates coosvector;
|
hegyi@1289
|
260 |
|
hegyi@1289
|
261 |
Graph g;
|
hegyi@1289
|
262 |
|
hegyi@1289
|
263 |
CoordinatesMap cm(g);
|
hegyi@1301
|
264 |
Graph::EdgeMap<double> cap(g);
|
hegyi@1289
|
265 |
|
hegyi@1289
|
266 |
//we create one object to read x coordinates
|
hegyi@1289
|
267 |
//and one to read y coordinate of nodes and write them to cm NodeMap.
|
hegyi@1289
|
268 |
CoordReaderMap xreader('x',cm);
|
hegyi@1289
|
269 |
CoordReaderMap yreader('y',cm);
|
hegyi@1289
|
270 |
|
hegyi@1290
|
271 |
std::ifstream is(argv[1]);
|
hegyi@1289
|
272 |
|
hegyi@1289
|
273 |
GraphReader<Graph> reader(is, g);
|
hegyi@1289
|
274 |
reader.addNodeMap("coordinates_x", xreader);
|
hegyi@1289
|
275 |
reader.addNodeMap("coordinates_y", yreader);
|
hegyi@1289
|
276 |
reader.run();
|
hegyi@1289
|
277 |
|
hegyi@1289
|
278 |
Gnome::Canvas::init();
|
hegyi@1289
|
279 |
Gtk::Main app(argc, argv);
|
hegyi@1289
|
280 |
|
hegyi@1289
|
281 |
MainWin mainwin("Displayed Graph", g, cm);
|
hegyi@1289
|
282 |
app.run(mainwin);
|
hegyi@1289
|
283 |
|
hegyi@1289
|
284 |
return 0;
|
hegyi@1289
|
285 |
}
|