src/work/peter/graph-displayer.cc
changeset 1365 c280de819a73
parent 1290 082fc511c2b9
equal deleted inserted replaced
2:df3763d71446 -1:000000000000
     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>
       
    14 #include <lemon/graph_writer.h>
       
    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
       
    40   bool event_handler(GdkEvent* e, Node n);
       
    41 
       
    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;  
       
    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.
       
    71 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
       
    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;
       
    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 				}
       
   125       }
       
   126     default: break;
       
   127   }
       
   128   return true;
       
   129 }
       
   130 
       
   131 GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm):g(gr),nodesmap(g),edgesmap(g),displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL)
       
   132 {
       
   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     }
       
   142     for (NodeIt i(g); i!=INVALID; ++i)
       
   143     {
       
   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));
       
   148     }
       
   149 
       
   150 }
       
   151 
       
   152 GraphDisplayerCanvas::~GraphDisplayerCanvas()
       
   153 {
       
   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();
       
   176 }
       
   177 
       
   178 
       
   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 {
       
   253   if(argc<2)
       
   254   {
       
   255       std::cerr << "USAGE: gd <input filename.lgf>" << endl;
       
   256       return 0;
       
   257   }
       
   258 
       
   259   Coordinates coosvector;
       
   260 
       
   261   Graph g;
       
   262 
       
   263   CoordinatesMap cm(g);
       
   264   Graph::EdgeMap<double> cap(g);
       
   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 
       
   271   std::ifstream is(argv[1]);
       
   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 }