Known bugs are eliminated from gui, and new ones are created by changing tool selectors to special radiobuttons, and by adding edgecreation-canceller function (right-click on any group element).
     1.1 --- a/gui/edit_win.cc	Mon Jun 13 17:21:55 2005 +0000
     1.2 +++ b/gui/edit_win.cc	Mon Jun 13 19:49:33 2005 +0000
     1.3 @@ -14,12 +14,23 @@
     1.4  {
     1.5    set_title(title);
     1.6    set_default_size(200, 50);
     1.7 -
     1.8 +  set_keep_above(true);
     1.9    signal_key_press_event().connect(sigc::mem_fun(*this, &EditWin::close_if_escape_is_pressed));
    1.10    
    1.11 +  //buttons array
    1.12 +  buttons=new (Gtk::RadioButton *) [TOOL_NUM];
    1.13 +  for(int i=0;i<TOOL_NUM;i++)
    1.14 +    {
    1.15 +      buttons[i]=NULL;
    1.16 +    }
    1.17 +
    1.18 +  Gtk::RadioButton::Group group;//=buttons[MOVE]->get_group();
    1.19 +
    1.20    //New node button
    1.21 -  button=new Gtk::Button("New Node");
    1.22 -  button->signal_clicked().connect
    1.23 +  buttons[CREATE_NODE]=new Gtk::RadioButton("New Node");
    1.24 +  buttons[CREATE_NODE]->set_mode(false);
    1.25 +  buttons[CREATE_NODE]->set_group(group);
    1.26 +  buttons[CREATE_NODE]->signal_clicked().connect
    1.27      (
    1.28       sigc::bind
    1.29       (
    1.30 @@ -27,11 +38,13 @@
    1.31        1
    1.32        )
    1.33       );
    1.34 -  table.attach(*button,0,1,0,1);
    1.35 +  table.attach(*buttons[CREATE_NODE],0,1,0,1);
    1.36  
    1.37    //New edge button
    1.38 -  button=new Gtk::Button("New Edge");
    1.39 -  button->signal_clicked().connect
    1.40 +  buttons[CREATE_EDGE]=new Gtk::RadioButton("New Edge");
    1.41 +  buttons[CREATE_EDGE]->set_mode(false);
    1.42 +  buttons[CREATE_EDGE]->set_group(group);
    1.43 +  buttons[CREATE_EDGE]->signal_clicked().connect
    1.44      (
    1.45       sigc::bind
    1.46       (
    1.47 @@ -39,11 +52,13 @@
    1.48        2
    1.49        )
    1.50       );
    1.51 -  table.attach(*button,1,2,0,1);
    1.52 +  table.attach(*buttons[CREATE_EDGE],1,2,0,1);
    1.53      
    1.54    //Move button
    1.55 -  button=new Gtk::Button("Move");
    1.56 -  button->signal_clicked().connect
    1.57 +  buttons[MOVE]=new Gtk::RadioButton("Move");
    1.58 +  buttons[MOVE]->set_mode(false);
    1.59 +  buttons[MOVE]->set_group(group);
    1.60 +  buttons[MOVE]->signal_clicked().connect
    1.61      (
    1.62       sigc::bind
    1.63       (
    1.64 @@ -51,8 +66,8 @@
    1.65        0
    1.66        )
    1.67       );
    1.68 -  table.attach(*button,0,1,1,2);
    1.69 -    
    1.70 +  table.attach(*buttons[MOVE],0,1,1,2);
    1.71 +      
    1.72    add(table);
    1.73  
    1.74    show_all_children();
     2.1 --- a/gui/edit_win.h	Mon Jun 13 17:21:55 2005 +0000
     2.2 +++ b/gui/edit_win.h	Mon Jun 13 19:49:33 2005 +0000
     2.3 @@ -15,15 +15,15 @@
     2.4  {
     2.5  protected:
     2.6    ///The \ref GraphDisplayerCanvas on which the graph will be drawn.
     2.7 -  ///It has to be known for this class, because
     2.8 -  ///when a map assigned to a certain attribute
     2.9 -  ///a function of the \ref GraphDisplayerCanvas will be called.
    2.10 +  ///It has to be known for this class, because the appropriate
    2.11 +  //callback function for each tool is implemented in that class
    2.12    GraphDisplayerCanvas & gdc;
    2.13  
    2.14 +  ///Table that holds the tools.
    2.15    Gtk::Table table;
    2.16    
    2.17 -  Gtk::Label * label;
    2.18 -  Gtk::Button * button;
    2.19 +  ///these buttons are RadioButtons with classic look
    2.20 +  Gtk::RadioButton ** buttons;
    2.21  
    2.22  public:
    2.23    ///Constructor of EditWin creates the widgets shown in EditWin.
     3.1 --- a/gui/graph_displayer_canvas.cc	Mon Jun 13 17:21:55 2005 +0000
     3.2 +++ b/gui/graph_displayer_canvas.cc	Mon Jun 13 19:49:33 2005 +0000
     3.3 @@ -6,6 +6,9 @@
     3.4    
     3.5    actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
     3.6  
     3.7 +  active_node=INVALID;
     3.8 +  active_edge=INVALID;
     3.9 +
    3.10    //set_center_scroll_region(true);
    3.11  
    3.12    //first edges are drawn, to hide joining with nodes later
    3.13 @@ -310,9 +313,12 @@
    3.14      case MOVE:
    3.15        actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::move_event_handler), false);
    3.16        break;
    3.17 +
    3.18 +      //it has to assigned to canvas, because all the canvas has to be monitored, not only the elements of the already drawn group
    3.19      case CREATE_NODE:
    3.20        actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_node_event_handler), false);
    3.21        break;
    3.22 +
    3.23      case CREATE_EDGE:
    3.24        actual_handler=displayed_graph.signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::create_edge_event_handler), false);
    3.25        break;
    3.26 @@ -343,11 +349,12 @@
    3.27      case GDK_BUTTON_RELEASE:
    3.28        isbutton=false;
    3.29        active_item=NULL;
    3.30 +      active_node=INVALID;
    3.31        updateScrollRegion();
    3.32        break;
    3.33      case GDK_MOTION_NOTIFY:
    3.34 -      //we only have to do sg. if the mouse button is pressed
    3.35 -      if(isbutton)
    3.36 +      //we only have to do sg. if the mouse button is pressed AND the click was on a node that was found in the set of nodes
    3.37 +      if(active_node!=INVALID)
    3.38        {
    3.39  	//new coordinates will be the old values,
    3.40  	//because the item will be moved to the
    3.41 @@ -416,6 +423,8 @@
    3.42  {
    3.43    switch(e->type)
    3.44      {
    3.45 +
    3.46 +      //draw the new node in red at the clicked place
    3.47      case GDK_BUTTON_PRESS:
    3.48        isbutton=true;
    3.49  
    3.50 @@ -429,6 +438,8 @@
    3.51        *(nodesmap[active_node]) << Gnome::Canvas::Properties::outline_color("black");
    3.52        (nodesmap[active_node])->show();
    3.53        break;
    3.54 +
    3.55 +      //move the new node
    3.56      case GDK_MOTION_NOTIFY:
    3.57        {
    3.58  	double world_motion_x, world_motion_y;
    3.59 @@ -440,10 +451,13 @@
    3.60  	move_event_handler(generated);      
    3.61  	break;
    3.62        }
    3.63 +
    3.64 +      //finalize the new node
    3.65      case GDK_BUTTON_RELEASE:
    3.66        isbutton=false;
    3.67        *active_item << Gnome::Canvas::Properties::fill_color("blue");
    3.68        active_item=NULL;
    3.69 +      active_node=INVALID;
    3.70        updateScrollRegion();
    3.71        break;
    3.72      default:
    3.73 @@ -457,73 +471,111 @@
    3.74    switch(e->type)
    3.75      {
    3.76      case GDK_BUTTON_PRESS:
    3.77 -      if(!active_item)
    3.78 +      //in edge creatino right button has special meaning
    3.79 +      if(e->button.button!=3)
    3.80  	{
    3.81 -	  //we mark the location of the event to be able to calculate parameters of dragging
    3.82 -	  clicked_x=e->button.x;
    3.83 -	  clicked_y=e->button.y;
    3.84 -	  active_item=(get_item_at(e->button.x, e->button.y));
    3.85 -	  active_node=INVALID;
    3.86 -	  for (NodeIt i(g); i!=INVALID; ++i)
    3.87 +	  //there is not yet selected node
    3.88 +	  if(active_node==INVALID)
    3.89  	    {
    3.90 -	      if(nodesmap[i]==active_item)
    3.91 +	      //we mark the location of the event to be able to calculate parameters of dragging
    3.92 +	      clicked_x=e->button.x;
    3.93 +	      clicked_y=e->button.y;
    3.94 +	      active_item=(get_item_at(e->button.x, e->button.y));
    3.95 +	      active_node=INVALID;
    3.96 +	      for (NodeIt i(g); i!=INVALID; ++i)
    3.97  		{
    3.98 -		  active_node=i;
    3.99 +		  if(nodesmap[i]==active_item)
   3.100 +		    {
   3.101 +		      active_node=i;
   3.102 +		    }
   3.103 +		}
   3.104 +	      //the clicked item is really a node
   3.105 +	      if(active_node!=INVALID)
   3.106 +		{
   3.107 +		  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   3.108 +		  isbutton=true;
   3.109 +		}
   3.110 +	      //clicked item was not a node. It could be e.g. edge.
   3.111 +	      else
   3.112 +		{
   3.113 +		  active_item=NULL;
   3.114  		}
   3.115  	    }
   3.116 -	  *(nodesmap[active_node]) << Gnome::Canvas::Properties::fill_color("red");
   3.117 -	  isbutton=true;
   3.118 -	}
   3.119 -      else
   3.120 -	{
   3.121 -	  target_item=(get_item_at(e->button.x, e->button.y));
   3.122 -	  Graph::NodeIt target_node=INVALID;
   3.123 -	  for (NodeIt i(g); i!=INVALID; ++i)
   3.124 +	  //we only have to do sg. if the mouse button
   3.125 +	  // is pressed already once AND the click was
   3.126 +	  // on a node that was found in the set of 
   3.127 +	  //nodes, and now we only search for the second 
   3.128 +	  //node
   3.129 +	  else
   3.130  	    {
   3.131 -	      if(nodesmap[i]==target_item)
   3.132 +	      target_item=(get_item_at(e->button.x, e->button.y));
   3.133 +	      Graph::NodeIt target_node=INVALID;
   3.134 +	      for (NodeIt i(g); i!=INVALID; ++i)
   3.135  		{
   3.136 -		  target_node=i;
   3.137 +		  if(nodesmap[i]==target_item)
   3.138 +		    {
   3.139 +		      target_node=i;
   3.140 +		    }
   3.141 +		}
   3.142 +	      //the clicked item is a node, the edge can be drawn
   3.143 +	      if(target_node!=INVALID)
   3.144 +		{
   3.145 +		  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   3.146 +
   3.147 +		  //creating new edge
   3.148 +		  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   3.149 +	  
   3.150 +		  //calculating coordinates of new edge
   3.151 +		  Gnome::Canvas::Points coos;
   3.152 +		  double x1, x2, y1, y2;
   3.153 +	  
   3.154 +		  active_item->get_bounds(x1, y1, x2, y2);
   3.155 +		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   3.156 +
   3.157 +		  target_item->get_bounds(x1, y1, x2, y2);
   3.158 +		  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   3.159 +
   3.160 +		  //drawing new edge
   3.161 +		  edgesmap[active_edge]=new Gnome::Canvas::Line(displayed_graph, coos);
   3.162 +		  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   3.163 +		  edgesmap[active_edge]->property_width_pixels().set_value(10);
   3.164 +
   3.165 +		  //redraw nodes to blank terminations of the new edge
   3.166 +		  target_item->raise_to_top();
   3.167 +		  active_item->raise_to_top();
   3.168 +
   3.169 +		  //initializing edge-text as well, to empty string
   3.170 +		  edgesmap[active_edge]->get_bounds(x1, y1, x2, y2);
   3.171 +		  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
   3.172 +		  edgetextmap[active_edge]->property_fill_color().set_value("black");
   3.173 +		}
   3.174 +	      //clicked item was not a node. it could be an e.g. edge. we do not deal with it furthermore.
   3.175 +	      else
   3.176 +		{
   3.177 +		  target_item=NULL;
   3.178  		}
   3.179  	    }
   3.180 -	  *(nodesmap[target_node]) << Gnome::Canvas::Properties::fill_color("red");
   3.181 -
   3.182 -	  //creating new edge
   3.183 -	  //	  Graph::Edge new_edge=g.addEdge(active_node, target_node);
   3.184 -	  active_edge=EdgeIt(g,g.addEdge(active_node, target_node));
   3.185 -	  
   3.186 -	  //calculating coordinates of new edge
   3.187 -	  Gnome::Canvas::Points coos;
   3.188 -	  double x1, x2, y1, y2;
   3.189 -	  
   3.190 -	  active_item->get_bounds(x1, y1, x2, y2);
   3.191 -	  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   3.192 -
   3.193 -	  target_item->get_bounds(x1, y1, x2, y2);
   3.194 -	  coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2));
   3.195 -
   3.196 -	  //drawing new edge
   3.197 -	  edgesmap[active_edge]=new Gnome::Canvas::Line(displayed_graph, coos);
   3.198 -	  *(edgesmap[active_edge]) << Gnome::Canvas::Properties::fill_color("green");
   3.199 -	  edgesmap[active_edge]->property_width_pixels().set_value(10);
   3.200 -
   3.201 -	  //redraw nodes to blank terminations of the new edge
   3.202 -	  target_item->raise_to_top();
   3.203 -	  active_item->raise_to_top();
   3.204 -
   3.205 -	  //initializing edge-text as well, to empty string
   3.206 -	  edgesmap[active_edge]->get_bounds(x1, y1, x2, y2);
   3.207 -	  edgetextmap[active_edge]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, "");
   3.208 -	  edgetextmap[active_edge]->property_fill_color().set_value("black");
   3.209  	}
   3.210        break;
   3.211      case GDK_BUTTON_RELEASE:
   3.212        isbutton=false;
   3.213 -      if(target_item)
   3.214 +      //we clear settings in two cases
   3.215 +      //1: the edge is ready (target_item has valid value)
   3.216 +      //2: the edge creation is cancelled with right button
   3.217 +      if((target_item)||(e->button.button==3))
   3.218  	{
   3.219 -	  *active_item << Gnome::Canvas::Properties::fill_color("blue");
   3.220 -	  *target_item << Gnome::Canvas::Properties::fill_color("blue");
   3.221 -	  active_item=NULL;
   3.222 -	  target_item=NULL;
   3.223 +	  if(active_item)
   3.224 +	    {
   3.225 +	      *active_item << Gnome::Canvas::Properties::fill_color("blue");
   3.226 +	      active_item=NULL;
   3.227 +	    }
   3.228 +	  if(target_item)
   3.229 +	    {
   3.230 +	      *target_item << Gnome::Canvas::Properties::fill_color("blue");
   3.231 +	      target_item=NULL;
   3.232 +	    }
   3.233 +	  active_node=INVALID;
   3.234 +	  active_edge=INVALID;
   3.235  	}
   3.236        break;
   3.237      default: