1  #include <graph_displayer_canvas.h>


2  #include <math.h>


3 


4  GraphDisplayerCanvas::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 edgetext 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].x20, cm[i].y20, 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 "<<(maxxminx)<<" dy "<<(maxyminy)<<" xrate "<<((maxxminx)/WIN_WIDTH)<<" yrate "<<((maxyminy)/WIN_HEIGHT)<<std::endl;


64  */


65  updateScrollRegion();


66  }


67 


68  GraphDisplayerCanvas::~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 


98  int 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 


108  int 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*(wmin)/(maxmin)<<std::endl;


122  Gdk::Color color;


123  if(max!=min)


124  {


125  color.set_rgb_p (0, 100*(wmin)/(maxmin), 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 


137  int 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,length1));


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 


179  bool 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.xclicked_x;


204  double dy=e>motion.yclicked_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 


257  bool 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 


265  void GraphDisplayerCanvas::zoomIn()


266  {


267  set_pixels_per_unit(


268  (1.0 + (double) zoom_step / 100.0) * get_pixels_per_unit());


269  }


270 


271  void GraphDisplayerCanvas::zoomOut()


272  {


273  set_pixels_per_unit(


274  (1.0  (double) zoom_step / 100.0) * get_pixels_per_unit());


275  }


276 


277  void 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 


307  void GraphDisplayerCanvas::zoom100()


308  {


309  set_pixels_per_unit(1.0);


310  }


311 


312  void 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  }

