src/work/peter/graph-displayer.cc
author hegyi
Fri, 01 Apr 2005 13:42:31 +0000
changeset 1290 082fc511c2b9
parent 1289 142633fc5014
child 1301 1f3baf3bd1f2
permissions -rw-r--r--
To run graph-displayer with sample input, type make run, but do not move the nodes, YET
     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_utils.h>
    15 #include <lemon/maps.h>
    16 #include <lemon/error.h>
    17 #include <lemon/xy.h>
    18 
    19 using namespace lemon;
    20 
    21 typedef xy<double> Coordinates;
    22 typedef ListGraph Graph;
    23 typedef Graph::NodeMap<Coordinates> CoordinatesMap;
    24 typedef Graph::Node Node;
    25 typedef Graph::EdgeIt EdgeIt;
    26 typedef Graph::NodeIt NodeIt;
    27 
    28 class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA
    29 {
    30   typedef Gnome::Canvas::CanvasAA Parent;
    31 
    32 public:
    33   GraphDisplayerCanvas(Graph &, CoordinatesMap &);
    34   virtual ~GraphDisplayerCanvas();
    35 
    36 private:
    37 
    38   ///Event handler function that handles dragging nodes of displayed_graph
    39   bool event_handler(GdkEvent* e, int b);
    40 
    41   ///Event handler function that handles dragging displayed_graph
    42   bool tri_mover(GdkEvent* e);
    43 
    44   ///Coordinates of Weight Point of tirangle
    45   Gnome::Art::Point * wp;
    46   ///Array of nodes of planefigure
    47   Gnome::Canvas::Ellipse ** nodes;
    48   ///Sides of planefigure
    49   Gnome::Canvas::Polygon * sides;
    50   ///Group of graphical elements of displayed_graph
    51   Gnome::Canvas::Group displayed_graph;
    52 
    53   ///Indicates whether the button of mouse is pressed or not
    54   bool isbutton;
    55 
    56   ///Number Of Elements - the number of nodes
    57   int noe;
    58 
    59   ///Array of coordinates
    60   double * coordinates;
    61 
    62   ///At this location was the mousebutton pressed.
    63   ///It helps to calculate the distance of dragging.
    64   double clicked_x, clicked_y;
    65 
    66   ///Remembers which Gnome::Canvas::Item was pressed.
    67   ///this variable is needed, because
    68   ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault
    69   ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution
    70   Gnome::Canvas::Item * active_item;
    71 
    72 
    73 };
    74 
    75 ///When we click on the weight point we can drag the whole planefigure. This function resolves it.
    76 bool GraphDisplayerCanvas::tri_mover(GdkEvent* e)
    77 {
    78   switch(e->type)
    79   {
    80     case GDK_BUTTON_PRESS:
    81       clicked_x=e->button.x;
    82       clicked_y=e->button.y;
    83       isbutton=true;
    84       break;
    85     case GDK_BUTTON_RELEASE:
    86       isbutton=false;
    87       active_item=NULL;
    88       break;
    89     case GDK_MOTION_NOTIFY:
    90       if(isbutton)
    91       {
    92         double dx=e->motion.x-clicked_x;
    93         double dy=e->motion.y-clicked_y;
    94 
    95         Gnome::Canvas::Points coos;
    96 
    97         for(int i=0;i<=noe;i++)
    98         {
    99           nodes[i]->move(dx,dy);
   100 
   101           double x=(coordinates[2*i]+=dx);
   102           double y=(coordinates[2*i+1]+=dy);
   103 
   104           if(i!=noe)coos.push_back(Gnome::Art::Point(x,y));
   105 
   106         }
   107 
   108         clicked_x=e->motion.x;
   109         clicked_y=e->motion.y;
   110 
   111         sides->property_points().set_value(coos);
   112       }
   113     default: break;
   114   }
   115   return true;
   116 }
   117 
   118 ///This function moves only one node of displayed_graph,
   119 ///but recalculate the location of weight point,
   120 ///and also redraw the sides of the planefigure.
   121 bool GraphDisplayerCanvas::event_handler(GdkEvent* e, int b)
   122 {
   123   switch(e->type)
   124   {
   125     case GDK_BUTTON_PRESS:
   126       clicked_x=e->button.x;
   127       clicked_y=e->button.y;
   128       active_item=(get_item_at(e->button.x, e->button.y));
   129       isbutton=true;
   130       break;
   131     case GDK_BUTTON_RELEASE:
   132       isbutton=false;
   133       active_item=NULL;
   134       break;
   135     case GDK_MOTION_NOTIFY:
   136       if(isbutton)
   137       {
   138         //double x1, y1, x2, y2;
   139         //(get_item_at(e->motion.x, e->motion.y))->get_bounds(x1, y1, x2, y2);
   140         //printf("Item coos: %d %d %d %d\n", (int)x1, (int)y1, (int)x2, (int)y2);
   141         //printf("Mouse is moved! %d %d\n",(int)e->motion.x,(int)e->motion.y);
   142         double dx=e->motion.x-clicked_x;
   143         double dy=e->motion.y-clicked_y;
   144         active_item->move(dx, dy);
   145 
   146         coordinates[2*b]+=dx;
   147         coordinates[2*b+1]+=dy;
   148 
   149         Gnome::Canvas::Points coos;
   150 
   151         double x_wp=0;
   152         double y_wp=0;
   153 
   154         for(int i=0;i<noe;i++)
   155         {
   156           coos.push_back(Gnome::Art::Point(coordinates[2*i], coordinates[2*i+1]));
   157 
   158           x_wp+=coordinates[2*i];
   159           y_wp+=coordinates[2*i+1];
   160         }
   161 
   162         sides->property_points().set_value(coos);
   163 
   164         x_wp/=noe;
   165         y_wp/=noe;
   166 
   167         dx=x_wp-coordinates[noe*2];
   168         dy=y_wp-coordinates[noe*2+1];
   169         nodes[noe]->move(dx, dy);
   170 
   171         coordinates[noe*2]+=dx;
   172         coordinates[noe*2+1]+=dy;
   173 
   174         clicked_x=e->motion.x;
   175         clicked_y=e->motion.y;
   176       }
   177     default: break;
   178   }
   179   return true;
   180 }
   181 
   182 GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & g, CoordinatesMap & cm):displayed_graph(*(root()), 0, 0),isbutton(false),active_item(NULL)
   183 {
   184     nodes=new Gnome::Canvas::Ellipse* [countNodes(g)];
   185     int sorszam=0;
   186 
   187     for (NodeIt i(g); i!=INVALID; ++i)
   188     {
   189 	nodes[sorszam]= new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
   190 	*(nodes[sorszam]) << Gnome::Canvas::Properties::fill_color("blue");
   191 	*(nodes[sorszam]) << Gnome::Canvas::Properties::outline_color("black");
   192 	(nodes[sorszam])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),sorszam));
   193 	sorszam++;
   194     }
   195 
   196     for (EdgeIt i(g); i!=INVALID; ++i)
   197     {
   198     }
   199 
   200 
   201 }
   202 
   203 GraphDisplayerCanvas::~GraphDisplayerCanvas()
   204 {
   205 }
   206 
   207 //MainWin:
   208 
   209 class MainWin : public Gtk::Window
   210 {
   211 public:
   212   MainWin(const std::string& title, Graph &, CoordinatesMap &);
   213 
   214 protected:
   215   //Member widgets:
   216   GraphDisplayerCanvas gd_canvas;
   217 };
   218 
   219 MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm):gd_canvas(graph, cm)
   220 {
   221   set_title (title);
   222   add(gd_canvas);
   223   set_default_size(900,600);
   224 
   225   show_all();
   226 }
   227 
   228 
   229 ///This class is responsible for being able
   230 ///to read xy datastructure from file. It is
   231 ///based on BaseMap. The set method sets the
   232 ///appropriate value in the final xy NodeMap
   233 ///that was given to the constructor.
   234 class CoordReaderMap: public MapBase <Node, double>
   235 {
   236     CoordinatesMap & cm;
   237     char xoy;
   238 
   239 public:
   240     CoordReaderMap(char xory, CoordinatesMap & coordmap);
   241     void set(Node node, double coord);
   242 };
   243 
   244 ///The constructor expects for an xy NodeMap,
   245 ///and we have to tell it, for which  value
   246 ///of the xy vector is responsible the actual
   247 ///copy.
   248 CoordReaderMap::CoordReaderMap(char xory, CoordinatesMap & coordmap): cm(coordmap)
   249 {
   250     switch(xory)
   251     {
   252 	case 'x':
   253 	case 'y':
   254 	    xoy=xory;
   255 	    break;
   256 	default:
   257 	    throw UninitializedParameter() ;
   258     }
   259 }
   260 
   261 ///set method sets the appropriate value in the
   262 ///xy type NodeMap that is under construction
   263 void CoordReaderMap::set(Node node, double coord)
   264 {
   265     switch(xoy)
   266     {
   267 	case 'x':
   268 	    cm[node].x=coord;
   269 	    break;
   270 	case 'y':
   271 	    cm[node].y=coord;
   272 	    break;
   273 	default:
   274 	    throw UninitializedParameter() ;
   275     }
   276 }
   277 
   278 //main():
   279 
   280 int main(int argc, char *argv[])
   281 {
   282   if(argc<2)
   283   {
   284       std::cerr << "USAGE: gd <input filename.lgf>" << endl;
   285       return 0;
   286   }
   287 
   288   Coordinates coosvector;
   289 
   290   Graph g;
   291 
   292   CoordinatesMap cm(g);
   293 
   294   //we create one object to read x coordinates
   295   //and one to read y coordinate of nodes and write them to cm NodeMap.
   296   CoordReaderMap xreader('x',cm);
   297   CoordReaderMap yreader('y',cm);
   298 
   299   std::ifstream is(argv[1]);
   300 
   301   GraphReader<Graph> reader(is, g);
   302   reader.addNodeMap("coordinates_x", xreader);
   303   reader.addNodeMap("coordinates_y", yreader);
   304   reader.run();
   305 
   306   for (NodeIt i(g); i!=INVALID; ++i)
   307       std::cout << " " << g.id(i) << " " << cm[i];
   308   std::cout << std::endl;
   309 
   310   Gnome::Canvas::init();
   311   Gtk::Main app(argc, argv);
   312 
   313   MainWin mainwin("Displayed Graph", g, cm);
   314   app.run(mainwin);
   315 
   316   return 0;
   317 }