| [1289] | 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. | 
|---|
|  | 5 |  | 
|---|
|  | 6 | #include <libgnomecanvasmm.h> | 
|---|
|  | 7 | #include <libgnomecanvasmm/polygon.h> | 
|---|
|  | 8 |  | 
|---|
|  | 9 | #include <fstream> | 
|---|
|  | 10 | #include <iostream> | 
|---|
|  | 11 |  | 
|---|
|  | 12 | #include <lemon/list_graph.h> | 
|---|
|  | 13 | #include <lemon/graph_reader.h> | 
|---|
| [1301] | 14 | #include <lemon/graph_writer.h> | 
|---|
| [1289] | 15 | #include <lemon/graph_utils.h> | 
|---|
|  | 16 | #include <lemon/maps.h> | 
|---|
|  | 17 | #include <lemon/error.h> | 
|---|
|  | 18 | #include <lemon/xy.h> | 
|---|
|  | 19 |  | 
|---|
|  | 20 | using namespace lemon; | 
|---|
|  | 21 |  | 
|---|
|  | 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; | 
|---|
|  | 28 |  | 
|---|
|  | 29 | class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA | 
|---|
|  | 30 | { | 
|---|
|  | 31 | typedef Gnome::Canvas::CanvasAA Parent; | 
|---|
|  | 32 |  | 
|---|
|  | 33 | public: | 
|---|
|  | 34 | GraphDisplayerCanvas(Graph &, CoordinatesMap &); | 
|---|
|  | 35 | virtual ~GraphDisplayerCanvas(); | 
|---|
|  | 36 |  | 
|---|
|  | 37 | private: | 
|---|
|  | 38 |  | 
|---|
|  | 39 | ///Event handler function that handles dragging nodes of displayed_graph | 
|---|
| [1301] | 40 | bool event_handler(GdkEvent* e, Node n); | 
|---|
| [1289] | 41 |  | 
|---|
| [1301] | 42 | ///The graph, on which we work | 
|---|
|  | 43 | Graph g; | 
|---|
|  | 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; | 
|---|
| [1289] | 48 | ///Group of graphical elements of displayed_graph | 
|---|
|  | 49 | Gnome::Canvas::Group displayed_graph; | 
|---|
|  | 50 |  | 
|---|
|  | 51 | ///Indicates whether the button of mouse is pressed or not | 
|---|
|  | 52 | bool isbutton; | 
|---|
|  | 53 |  | 
|---|
|  | 54 | ///At this location was the mousebutton pressed. | 
|---|
|  | 55 | ///It helps to calculate the distance of dragging. | 
|---|
|  | 56 | double clicked_x, clicked_y; | 
|---|
|  | 57 |  | 
|---|
|  | 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; | 
|---|
|  | 63 |  | 
|---|
|  | 64 |  | 
|---|
|  | 65 | }; | 
|---|
|  | 66 |  | 
|---|
|  | 67 |  | 
|---|
|  | 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. | 
|---|
| [1301] | 71 | bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n) | 
|---|
| [1289] | 72 | { | 
|---|
|  | 73 | switch(e->type) | 
|---|
|  | 74 | { | 
|---|
|  | 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)); | 
|---|
|  | 79 | isbutton=true; | 
|---|
|  | 80 | break; | 
|---|
|  | 81 | case GDK_BUTTON_RELEASE: | 
|---|
|  | 82 | isbutton=false; | 
|---|
|  | 83 | active_item=NULL; | 
|---|
|  | 84 | break; | 
|---|
|  | 85 | case GDK_MOTION_NOTIFY: | 
|---|
|  | 86 | if(isbutton) | 
|---|
|  | 87 | { | 
|---|
|  | 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; | 
|---|
| [1301] | 93 |  | 
|---|
|  | 94 | EdgeIt e; | 
|---|
|  | 95 |  | 
|---|
|  | 96 | g.firstOut(e,n); | 
|---|
|  | 97 | for(;e!=INVALID;g.nextOut(e)) | 
|---|
|  | 98 | { | 
|---|
|  | 99 | Gnome::Canvas::Points coos; | 
|---|
|  | 100 | double x1, x2, y1, y2; | 
|---|
|  | 101 |  | 
|---|
|  | 102 | nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); | 
|---|
|  | 103 | coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); | 
|---|
|  | 104 |  | 
|---|
|  | 105 | nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); | 
|---|
|  | 106 | coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); | 
|---|
|  | 107 |  | 
|---|
|  | 108 | edgesmap[e]->property_points().set_value(coos); | 
|---|
|  | 109 | } | 
|---|
|  | 110 |  | 
|---|
|  | 111 | g.firstIn(e,n); | 
|---|
|  | 112 | for(;e!=INVALID;g.nextIn(e)) | 
|---|
|  | 113 | { | 
|---|
|  | 114 | Gnome::Canvas::Points coos; | 
|---|
|  | 115 | double x1, x2, y1, y2; | 
|---|
|  | 116 |  | 
|---|
|  | 117 | nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); | 
|---|
|  | 118 | coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); | 
|---|
|  | 119 |  | 
|---|
|  | 120 | nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); | 
|---|
|  | 121 | coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); | 
|---|
|  | 122 |  | 
|---|
|  | 123 | edgesmap[e]->property_points().set_value(coos); | 
|---|
|  | 124 | } | 
|---|
| [1289] | 125 | } | 
|---|
|  | 126 | default: break; | 
|---|
|  | 127 | } | 
|---|
|  | 128 | return true; | 
|---|
|  | 129 | } | 
|---|
|  | 130 |  | 
|---|
| [1301] | 131 | GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm):g(gr),nodesmap(g),edgesmap(g),displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL) | 
|---|
| [1289] | 132 | { | 
|---|
| [1301] | 133 | for (EdgeIt i(g); i!=INVALID; ++i) | 
|---|
|  | 134 | { | 
|---|
|  | 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); | 
|---|
|  | 141 | } | 
|---|
| [1289] | 142 | for (NodeIt i(g); i!=INVALID; ++i) | 
|---|
|  | 143 | { | 
|---|
| [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); | 
|---|
|  | 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)); | 
|---|
| [1289] | 148 | } | 
|---|
|  | 149 |  | 
|---|
|  | 150 | } | 
|---|
|  | 151 |  | 
|---|
|  | 152 | GraphDisplayerCanvas::~GraphDisplayerCanvas() | 
|---|
|  | 153 | { | 
|---|
| [1301] | 154 | Graph::NodeMap <int> id(g); | 
|---|
|  | 155 | Graph::NodeMap <double> xc(g); | 
|---|
|  | 156 | Graph::NodeMap <double> yc(g); | 
|---|
|  | 157 |  | 
|---|
|  | 158 | int j=1; | 
|---|
|  | 159 |  | 
|---|
|  | 160 | for (NodeIt i(g); i!=INVALID; ++i) | 
|---|
|  | 161 | { | 
|---|
|  | 162 | double x1,y1,x2,y2; | 
|---|
|  | 163 | nodesmap[i]->get_bounds(x1, y1, x2, y2); | 
|---|
|  | 164 |  | 
|---|
|  | 165 | id[i]=j++; | 
|---|
|  | 166 | xc[i]=(x1+x2)/2; | 
|---|
|  | 167 | yc[i]=(y1+y2)/2; | 
|---|
|  | 168 | } | 
|---|
|  | 169 |  | 
|---|
|  | 170 | GraphWriter<Graph> writer(std::cout,g); | 
|---|
|  | 171 |  | 
|---|
|  | 172 | writer.addNodeMap("id", id); | 
|---|
|  | 173 | writer.addNodeMap("coordinates_x", xc); | 
|---|
|  | 174 | writer.addNodeMap("coordinates_y", yc); | 
|---|
|  | 175 | writer.run(); | 
|---|
| [1289] | 176 | } | 
|---|
|  | 177 |  | 
|---|
| [1301] | 178 |  | 
|---|
| [1289] | 179 | //MainWin: | 
|---|
|  | 180 | class MainWin : public Gtk::Window | 
|---|
|  | 181 | { | 
|---|
|  | 182 | public: | 
|---|
|  | 183 | MainWin(const std::string& title, Graph &, CoordinatesMap &); | 
|---|
|  | 184 |  | 
|---|
|  | 185 | protected: | 
|---|
|  | 186 | //Member widgets: | 
|---|
|  | 187 | GraphDisplayerCanvas gd_canvas; | 
|---|
|  | 188 | }; | 
|---|
|  | 189 |  | 
|---|
|  | 190 | MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm) | 
|---|
|  | 191 | { | 
|---|
|  | 192 | set_title (title); | 
|---|
|  | 193 | add(gd_canvas); | 
|---|
|  | 194 | set_default_size(900,600); | 
|---|
|  | 195 |  | 
|---|
|  | 196 | show_all(); | 
|---|
|  | 197 | } | 
|---|
|  | 198 |  | 
|---|
|  | 199 |  | 
|---|
|  | 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> | 
|---|
|  | 206 | { | 
|---|
|  | 207 | CoordinatesMap & cm; | 
|---|
|  | 208 | char xoy; | 
|---|
|  | 209 |  | 
|---|
|  | 210 | public: | 
|---|
|  | 211 | CoordReaderMap(char xory, CoordinatesMap & coordmap); | 
|---|
|  | 212 | void set(Node node, double coord); | 
|---|
|  | 213 | }; | 
|---|
|  | 214 |  | 
|---|
|  | 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 | 
|---|
|  | 218 | ///copy. | 
|---|
|  | 219 | CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap) | 
|---|
|  | 220 | { | 
|---|
|  | 221 | switch(xory) | 
|---|
|  | 222 | { | 
|---|
|  | 223 | case 'x': | 
|---|
|  | 224 | case 'y': | 
|---|
|  | 225 | xoy=xory; | 
|---|
|  | 226 | break; | 
|---|
|  | 227 | default: | 
|---|
|  | 228 | throw UninitializedParameter() ; | 
|---|
|  | 229 | } | 
|---|
|  | 230 | } | 
|---|
|  | 231 |  | 
|---|
|  | 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) | 
|---|
|  | 235 | { | 
|---|
|  | 236 | switch(xoy) | 
|---|
|  | 237 | { | 
|---|
|  | 238 | case 'x': | 
|---|
|  | 239 | cm[node].x=coord; | 
|---|
|  | 240 | break; | 
|---|
|  | 241 | case 'y': | 
|---|
|  | 242 | cm[node].y=coord; | 
|---|
|  | 243 | break; | 
|---|
|  | 244 | default: | 
|---|
|  | 245 | throw UninitializedParameter() ; | 
|---|
|  | 246 | } | 
|---|
|  | 247 | } | 
|---|
|  | 248 |  | 
|---|
|  | 249 | //main(): | 
|---|
|  | 250 |  | 
|---|
|  | 251 | int main(int argc, char *argv[]) | 
|---|
|  | 252 | { | 
|---|
| [1290] | 253 | if(argc<2) | 
|---|
|  | 254 | { | 
|---|
|  | 255 | std::cerr << "USAGE: gd <input filename.lgf>" << endl; | 
|---|
|  | 256 | return 0; | 
|---|
|  | 257 | } | 
|---|
| [1289] | 258 |  | 
|---|
|  | 259 | Coordinates coosvector; | 
|---|
|  | 260 |  | 
|---|
|  | 261 | Graph g; | 
|---|
|  | 262 |  | 
|---|
|  | 263 | CoordinatesMap cm(g); | 
|---|
| [1301] | 264 | Graph::EdgeMap<double> cap(g); | 
|---|
| [1289] | 265 |  | 
|---|
|  | 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); | 
|---|
|  | 270 |  | 
|---|
| [1290] | 271 | std::ifstream is(argv[1]); | 
|---|
| [1289] | 272 |  | 
|---|
|  | 273 | GraphReader<Graph> reader(is, g); | 
|---|
|  | 274 | reader.addNodeMap("coordinates_x", xreader); | 
|---|
|  | 275 | reader.addNodeMap("coordinates_y", yreader); | 
|---|
|  | 276 | reader.run(); | 
|---|
|  | 277 |  | 
|---|
|  | 278 | Gnome::Canvas::init(); | 
|---|
|  | 279 | Gtk::Main app(argc, argv); | 
|---|
|  | 280 |  | 
|---|
|  | 281 | MainWin mainwin("Displayed Graph", g, cm); | 
|---|
|  | 282 | app.run(mainwin); | 
|---|
|  | 283 |  | 
|---|
|  | 284 | return 0; | 
|---|
|  | 285 | } | 
|---|