COIN-OR::LEMON - Graph Library

source: glemon-0.x/graph_displayer_canvas.cc @ 5:b7c36be1e35c

gui
Last change on this file since 5:b7c36be1e35c was 5:b7c36be1e35c, checked in by Akos Ladanyi, 19 years ago
  • Property exe set to *
File size: 9.6 KB
Line 
1#include <graph_displayer_canvas.h>
2#include <math.h>
3
4GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm, MapStorage & ms):g(gr),nodesmap(g),edgesmap(g),edgetextmap(g),displayed_graph(*(root()), 0, 0),mapstorage(ms),isbutton(false),active_item(NULL)
5{
6  //set_center_scroll_region(true);
7
8  //first edges are drawn, to hide joining with nodes later
9
10  for (EdgeIt i(g); i!=INVALID; ++i)
11  {
12
13    //drawing green lines, coordinates are from cm
14
15    Gnome::Canvas::Points coos;
16    coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y));
17    coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y));
18   
19    edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos);
20    *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green");
21    edgesmap[i]->property_width_pixels().set_value(10);   
22   
23    //initializing edge-text as well, to empty string
24
25    double x1, x2, y1, y2;
26    edgesmap[i]->get_bounds(x1, y1, x2, y2);
27   
28    edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
29    edgetextmap[i]->property_fill_color().set_value("black");
30  }
31
32  //afterwards nodes come to be drawn
33
34  NodeIt i(g);
35  int maxx=0, maxy=0, minx=(int)cm[i].x, miny=(int)cm[i].y;
36
37  for (; i!=INVALID; ++i)
38  {
39    //minimum and maximum is gathered to be able to zoom to the graph correctly (whole figure should be seen)
40
41    if(cm[i].x>maxx)maxx=(int)cm[i].x;
42    if(cm[i].y>maxy)maxy=(int)cm[i].y;
43    if(cm[i].x<minx)minx=(int)cm[i].x;
44    if(cm[i].y<miny)miny=(int)cm[i].y;
45
46    //drawing bule nodes, with black line around them
47
48    nodesmap[i]=new Gnome::Canvas::Ellipse(displayed_graph, cm[i].x-20, cm[i].y-20, cm[i].x+20, cm[i].y+20);
49    *(nodesmap[i]) << Gnome::Canvas::Properties::fill_color("blue");
50    *(nodesmap[i]) << Gnome::Canvas::Properties::outline_color("black");
51    (nodesmap[i])->signal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i));
52  }
53
54/*
55  //setting zoom to be able to see the whole graph on the canvas
56
57  double biggest_x=(abs(maxx)>abs(minx))?(abs(maxx)+80):(abs(minx)+80);
58  double biggest_y=(abs(maxy)>abs(miny))?(abs(maxy)+80):(abs(miny)+80);
59
60  set_pixels_per_unit((biggest_x>biggest_y)?(WIN_WIDTH/biggest_x/2):(WIN_HEIGHT/biggest_y/2));
61  std::cout<<abs(maxx)<<" "<<abs(minx)<<" big x "<<biggest_x<<" "<<abs(maxy)<<" "<<abs(miny)<<" big y "<<biggest_y<<std::endl;
62  std::cout<<maxx<<" "<<minx<<" big x "<<biggest_x<<" "<<maxy<<" "<<miny<<" big y "<<biggest_y<<std::endl;
63  std::cout<<"dx "<<(maxx-minx)<<" dy "<<(maxy-miny)<<" xrate "<<((maxx-minx)/WIN_WIDTH)<<" yrate "<<((maxy-miny)/WIN_HEIGHT)<<std::endl;
64*/
65  updateScrollRegion();
66}
67
68GraphDisplayerCanvas::~GraphDisplayerCanvas()
69{
70
71  //writing out the end state of the graph
72  //\todo all the maps has to be write out!
73
74  Graph::NodeMap <int> id(g);
75  Graph::NodeMap <double> xc(g);
76  Graph::NodeMap <double> yc(g);
77 
78  int j=1;
79 
80  for (NodeIt i(g); i!=INVALID; ++i)
81  {
82    double x1,y1,x2,y2;
83    nodesmap[i]->get_bounds(x1, y1, x2, y2);
84   
85    id[i]=j++;
86    xc[i]=(x1+x2)/2;
87    yc[i]=(y1+y2)/2;
88  }
89
90  GraphWriter<Graph> writer(std::cout,g);
91 
92  writer.writeNodeMap("id", id);
93  writer.writeNodeMap("coordinates_x", xc);
94  writer.writeNodeMap("coordinates_y", yc);
95  writer.run();
96}
97
98int GraphDisplayerCanvas::changeLineWidth (std::string mapname)
99{
100  for (EdgeIt i(g); i!=INVALID; ++i)
101  {
102    int w=(int)(*(mapstorage.edgemap_storage)[mapname])[i];
103    edgesmap[i]->property_width_pixels().set_value(w);
104  }
105  return 0;
106};
107
108int GraphDisplayerCanvas::changeColor (std::string mapname)
109
110
111  //function maps the range of the maximum and
112  //the minimum of the nodemap to the range of
113  //green in RGB
114
115  for (EdgeIt i(g); i!=INVALID; ++i)
116  {
117    double w=(*(mapstorage.edgemap_storage)[mapname])[i];
118    double max=mapstorage.maxOfEdgeMap(mapname);
119    double min=mapstorage.minOfEdgeMap(mapname);
120     
121    //std::cout<<w<<" "<<max<<" "<<min<<" "<<100*(w-min)/(max-min)<<std::endl;
122    Gdk::Color color;
123    if(max!=min)
124    {
125      color.set_rgb_p (0, 100*(w-min)/(max-min), 0);
126    }
127    else
128    {
129      color.set_rgb_p (0, 100, 0);
130    }
131
132    edgesmap[i]->property_fill_color_gdk().set_value(color);
133  }
134  return 0;
135};
136
137int GraphDisplayerCanvas::changeText (std::string mapname)
138{
139
140  //the number in the map will be written on the edge
141  //EXCEPT when the name of the map is Text, because
142  //in that case empty string will be written, because
143  //that is the deleter map
144  //\todo isn't it a bit woodcutter?
145
146  for (EdgeIt i(g); i!=INVALID; ++i)
147  {
148    if(mapname!="Text")
149    {
150      double number=(*(mapstorage.edgemap_storage)[mapname])[i];
151      int length=(int)(floor(log(number)/log(10)))+1;
152      int maxpos=(int)(pow(10,length-1));
153      int strl=length+1+RANGE;
154      char * str=new char[strl];
155      str[length]='.';
156      str[strl]='\0';
157     
158      for(int j=0;j<strl;j++)
159      {
160        if(j!=length)
161        {
162          int digit=(int)(number/maxpos);
163          str[j]=(digit+'0');
164          number-=digit*maxpos;
165          number*=10;
166        }
167      }
168     
169      edgetextmap[i]->property_text().set_value(str);
170    }
171    else
172    {
173      edgetextmap[i]->property_text().set_value("");
174    }
175  }
176  return 0;
177};
178
179bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n)
180{
181  switch(e->type)
182  {
183    case GDK_BUTTON_PRESS:
184      //we mark the location of the event to be able to calculate parameters of dragging
185      clicked_x=e->button.x;
186      clicked_y=e->button.y;
187      active_item=(get_item_at(e->button.x, e->button.y));
188      isbutton=true;
189      break;
190    case GDK_BUTTON_RELEASE:
191      isbutton=false;
192      active_item=NULL;
193      break;
194    case GDK_MOTION_NOTIFY:
195      //we only have to do sg. if the mouse button is pressed
196      if(isbutton)
197      {
198        //new coordinates will be the old values,
199        //because the item will be moved to the
200        //new coordinate therefore the new movement
201        //has to be calculated from here
202
203        double dx=e->motion.x-clicked_x;
204        double dy=e->motion.y-clicked_y;
205        active_item->move(dx, dy);
206        clicked_x=e->motion.x;
207        clicked_y=e->motion.y;
208
209        //all the edges connected to the moved point has to be redrawn
210
211        EdgeIt e;
212        g.firstOut(e,n);
213        for(;e!=INVALID;g.nextOut(e))
214        {
215            Gnome::Canvas::Points coos;
216            double x1, x2, y1, y2;
217
218            nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
219            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
220
221            nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
222            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
223
224            edgesmap[e]->property_points().set_value(coos);
225
226            edgesmap[e]->get_bounds(x1, y1, x2, y2);
227
228            edgetextmap[e]->property_x().set_value((x1+x2)/2);
229            edgetextmap[e]->property_y().set_value((y1+y2)/2);
230        }
231
232        g.firstIn(e,n);
233        for(;e!=INVALID;g.nextIn(e))
234        {
235            Gnome::Canvas::Points coos;
236            double x1, x2, y1, y2;
237
238            nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2);
239            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
240
241            nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2);
242            coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
243
244            edgesmap[e]->property_points().set_value(coos);
245
246            edgesmap[e]->get_bounds(x1, y1, x2, y2);
247
248            edgetextmap[e]->property_x().set_value((x1+x2)/2);
249            edgetextmap[e]->property_y().set_value((y1+y2)/2);
250        }
251      }
252    default: break;
253  }
254  return true;
255}
256
257bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event)
258{
259  Gnome::Canvas::CanvasAA::on_expose_event(event);
260  //usleep(10000);
261  //rezoom();
262  return true;
263}
264
265void GraphDisplayerCanvas::zoomIn()
266{
267  set_pixels_per_unit(
268      (1.0 + (double) zoom_step / 100.0) * get_pixels_per_unit());
269}
270
271void GraphDisplayerCanvas::zoomOut()
272{
273  set_pixels_per_unit(
274      (1.0 - (double) zoom_step / 100.0) * get_pixels_per_unit());
275}
276
277void GraphDisplayerCanvas::zoomFit()
278{
279  // get the height and width of the canvas
280  Gtk::Allocation a = get_allocation();
281  int aw = a.get_width();
282  int ah = a.get_height();
283  // add some space
284  aw -= 5; if (aw < 0) aw = 0;
285  ah -= 5; if (ah < 0) ah = 0;
286  //std::cout << "aw=" << aw << " ah=" << ah << std::endl;
287
288  // get the bounding box of the graph
289  set_pixels_per_unit(1.0); // I don't really understand why this is necessary
290  double wx1, wy1, wx2, wy2;
291  double cx1, cy1, cx2, cy2;
292  Gnome::Canvas::Item* pCanvasItem = root();
293  pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
294  //std::cout << "root bounds: " << wx1 << " " << wy1 << " " << wx2 << " " << wy2 << std::endl;
295  w2c(wx1, wy1, cx1, cy1);
296  w2c(wx2, wy2, cx2, cy2);
297  //std::cout << "root bounds (c): " << cx1 << " " << cy1 << " " << cx2 << " " << cy2 << std::endl;
298  //std::cout << "cx2 - cx1=" << fabs(cx2 - cx1) << " cy2 - cy1=" << fabs(cy2 - cy1) << std::endl;
299
300  // fit the graph to the window
301  double ppu1 = (double) aw / fabs(cx2 - cx1);
302  double ppu2 = (double) ah / fabs(cy2 - cy1);
303  //std::cout << "ppu1=" << ppu1 << " ppu2=" << ppu2 << std::endl;
304  (ppu1 < ppu2) ? set_pixels_per_unit(ppu1) : set_pixels_per_unit(ppu2);
305}
306
307void GraphDisplayerCanvas::zoom100()
308{
309  set_pixels_per_unit(1.0);
310}
311
312void GraphDisplayerCanvas::updateScrollRegion()
313{
314  double wx1, wy1, wx2, wy2;
315  int cx1, cy1, cx2, cy2;
316  Gnome::Canvas::Item* pCanvasItem = root();
317  pCanvasItem->get_bounds(wx1, wy1, wx2, wy2);
318  w2c(wx1, wy1, cx1, cy1);
319  w2c(wx2, wy2, cx2, cy2);
320  set_scroll_region(cx1, cy1, cx2, cy2);
321}
Note: See TracBrowser for help on using the repository browser.