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