src/work/peter/graph-displayer.cc
author hegyi
Mon, 04 Apr 2005 19:22:04 +0000
changeset 1301 1f3baf3bd1f2
parent 1290 082fc511c2b9
permissions -rw-r--r--
Graph displayer displays graphs now.
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
}