gui/graph_displayer_canvas.cc
author athos
Thu, 02 Jun 2005 14:43:45 +0000
changeset 1443 70781827eb2f
parent 1441 fd4b6f6d592a
child 1444 5fcd69785959
permissions -rwxr-xr-x
Documentation review.
     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 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 
    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*(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 
   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,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 
   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.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 
   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 }