Node and edge editor button are the same furthermore.
authorhegyi
Tue, 19 Sep 2006 07:43:55 +0000
changeset 149930e838ad5b6
parent 148 5adf29662354
child 150 86273bfe0e4d
Node and edge editor button are the same furthermore.
all_include.h
graph_displayer_canvas-event.cc
graph_displayer_canvas.cc
graph_displayer_canvas.h
main_win.cc
     1.1 --- a/all_include.h	Mon Sep 18 16:02:20 2006 +0000
     1.2 +++ b/all_include.h	Tue Sep 19 07:43:55 2006 +0000
     1.3 @@ -18,7 +18,7 @@
     1.4  
     1.5  enum {E_WIDTH, E_COLOR, E_TEXT, EDGE_PROPERTY_NUM}; // edge properties;
     1.6  enum {N_RADIUS, N_COLOR, N_TEXT, NODE_PROPERTY_NUM}; // node properties;
     1.7 -enum {MOVE, CREATE_NODE, CREATE_EDGE, ERASER, EDGE_MAP_EDIT, NODE_MAP_EDIT, TOOL_NUM}; // tools;
     1.8 +enum {MOVE, CREATE_NODE, CREATE_EDGE, ERASER, MAP_EDIT, TOOL_NUM}; // tools;
     1.9  #define RANGE 3
    1.10  #define WIN_WIDTH 900
    1.11  #define WIN_HEIGHT 600
     2.1 --- a/graph_displayer_canvas-event.cc	Mon Sep 18 16:02:20 2006 +0000
     2.2 +++ b/graph_displayer_canvas-event.cc	Tue Sep 19 07:43:55 2006 +0000
     2.3 @@ -27,9 +27,7 @@
     2.4  	    createEdgeEventHandler(generated);      
     2.5  	    break;
     2.6  	  }
     2.7 -	case EDGE_MAP_EDIT:
     2.8 -	  //has to do the same thing as in the case of NODE_MAP_EDIT
     2.9 -	case NODE_MAP_EDIT:
    2.10 +	case MAP_EDIT:
    2.11  	  {
    2.12  	    break;
    2.13  	  }
    2.14 @@ -63,13 +61,9 @@
    2.15  	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::eraserEventHandler), false);
    2.16  	  break;
    2.17  
    2.18 -	case EDGE_MAP_EDIT:
    2.19 +	case MAP_EDIT:
    2.20  	  grab_focus();
    2.21 -	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
    2.22 -	  break;
    2.23 -
    2.24 -	case NODE_MAP_EDIT:
    2.25 -	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
    2.26 +	  actual_handler=signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
    2.27  	  break;
    2.28  
    2.29  	default:
    2.30 @@ -622,179 +616,163 @@
    2.31    return false;
    2.32  }
    2.33  
    2.34 -bool GraphDisplayerCanvas::edgeMapEditEventHandler(GdkEvent* e)
    2.35 +bool GraphDisplayerCanvas::mapEditEventHandler(GdkEvent* e)
    2.36  {
    2.37 -  if(actual_tool==EDGE_MAP_EDIT)
    2.38 -  {
    2.39 -    switch(e->type)
    2.40 +  if(actual_tool==MAP_EDIT)
    2.41      {
    2.42 -      case GDK_BUTTON_PRESS:
    2.43 -        {
    2.44 -          //for determine, whether it was an edge
    2.45 -          Edge clicked_edge=INVALID;
    2.46 +      switch(e->type)
    2.47 +	{
    2.48 +	case GDK_BUTTON_PRESS:
    2.49 +	  {
    2.50 +	    //for determine, whether it was an edge
    2.51 +	    Edge clicked_edge=INVALID;
    2.52 +	    //for determine, whether it was a node
    2.53 +	    Node clicked_node=INVALID;
    2.54  
    2.55 -          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
    2.56 -          active_item=(get_item_at(clicked_x, clicked_y));
    2.57 +	    window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
    2.58 +	    active_item=(get_item_at(clicked_x, clicked_y));
    2.59  
    2.60 -          //find the activated item between texts
    2.61 -          for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
    2.62 -          {
    2.63 -            //at the same time only one can be active
    2.64 -            if(edgetextmap[i]==active_item)
    2.65 -            {
    2.66 -              clicked_edge=i;
    2.67 -            }
    2.68 -          }
    2.69 +	    //find the activated item between text of nodes
    2.70 +	    for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
    2.71 +	      {
    2.72 +		//at the same time only one can be active
    2.73 +		if(nodetextmap[i]==active_item)
    2.74 +		  {
    2.75 +		    clicked_node=i;
    2.76 +		  }
    2.77 +	      }
    2.78  
    2.79 -          //if it was not between texts, search for it between edges
    2.80 -          if(clicked_edge==INVALID)
    2.81 -          {
    2.82 -            for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
    2.83 -            {
    2.84 -              //at the same time only one can be active
    2.85 -              if((edgesmap[i]==active_item)||(edgetextmap[i]==active_item))
    2.86 -              {
    2.87 -                clicked_edge=i;
    2.88 -              }
    2.89 -            }
    2.90 -          }
    2.91 - 
    2.92 -          //if it was really an edge...
    2.93 -          if(clicked_edge!=INVALID)
    2.94 -          {
    2.95 -            // the id map is not editable
    2.96 -            if (edgemap_to_edit == "label") return 0;
    2.97 +	    //if there was not, search for it between nodes
    2.98 +	    if(clicked_node==INVALID)
    2.99 +	      {
   2.100 +		for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   2.101 +		  {
   2.102 +		    //at the same time only one can be active
   2.103 +		    if(nodesmap[i]==active_item)
   2.104 +		      {
   2.105 +			clicked_node=i;
   2.106 +		      }
   2.107 +		  }
   2.108 +	      }
   2.109  
   2.110 -            //and there is activated map
   2.111 -            if(edgetextmap[clicked_edge]->property_text().get_value()!="")
   2.112 -            {
   2.113 -              //activate the general variable for it
   2.114 -              active_edge=clicked_edge;
   2.115 +	    if(clicked_node==INVALID)
   2.116 +	      {
   2.117 +		//find the activated item between texts
   2.118 +		for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   2.119 +		  {
   2.120 +		    //at the same time only one can be active
   2.121 +		    if(edgetextmap[i]==active_item)
   2.122 +		      {
   2.123 +			clicked_edge=i;
   2.124 +		      }
   2.125 +		  }
   2.126  
   2.127 -              //create a dialog
   2.128 -              Gtk::Dialog dialog("Edit value", true);
   2.129 -              dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   2.130 -              dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   2.131 -              Gtk::VBox* vbox = dialog.get_vbox();
   2.132 -              Gtk::SpinButton spin(0.0, 4);
   2.133 -              spin.set_increments(1.0, 10.0);
   2.134 -              spin.set_range(-1000000.0, 1000000.0);
   2.135 -              spin.set_numeric(true);
   2.136 -              vbox->add(spin);
   2.137 -              spin.show();
   2.138 -              switch (dialog.run())
   2.139 -              {
   2.140 -                case Gtk::RESPONSE_NONE:
   2.141 -                case Gtk::RESPONSE_CANCEL:
   2.142 -                  break;
   2.143 -                case Gtk::RESPONSE_ACCEPT:
   2.144 -                  double new_value = spin.get_value();
   2.145 -                  (*(mytab.mapstorage).edgemap_storage[edgemap_to_edit])[active_edge] =
   2.146 -                    new_value;
   2.147 -                  std::ostringstream ostr;
   2.148 -                  ostr << new_value;
   2.149 -                  edgetextmap[active_edge]->property_text().set_value(
   2.150 -                      ostr.str());
   2.151 -                  //mapwin.updateEdge(active_edge);
   2.152 -//                   mapwin.updateEdge(Edge(INVALID));
   2.153 -                  propertyUpdate(Edge(INVALID));
   2.154 -              }
   2.155 -            }
   2.156 -          }
   2.157 -          break;
   2.158 -        }
   2.159 -      default:
   2.160 -        break;
   2.161 +		//if it was not between texts, search for it between edges
   2.162 +		if(clicked_edge==INVALID)
   2.163 +		  {
   2.164 +		    for (EdgeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   2.165 +		      {
   2.166 +			//at the same time only one can be active
   2.167 +			if((edgesmap[i]->getLine())==active_item)
   2.168 +			  {
   2.169 +			    clicked_edge=i;
   2.170 +			  }
   2.171 +		      }
   2.172 +		  }
   2.173 +	      }
   2.174 +
   2.175 +	    //if it was really a node...
   2.176 +	    if(clicked_node!=INVALID)
   2.177 +	      {
   2.178 +		// the id map is not editable
   2.179 +		if (nodemap_to_edit == "label") return 0;
   2.180 +
   2.181 +		//and there is activated map
   2.182 +		if(nodetextmap[clicked_node]->property_text().get_value()!="")
   2.183 +		  {
   2.184 +		    //activate the general variable for it
   2.185 +		    active_node=clicked_node;
   2.186 +
   2.187 +		    //create a dialog
   2.188 +		    Gtk::Dialog dialog("Edit value", true);
   2.189 +		    dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   2.190 +		    dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   2.191 +		    Gtk::VBox* vbox = dialog.get_vbox();
   2.192 +		    Gtk::SpinButton spin(0.0, 4);
   2.193 +		    spin.set_increments(1.0, 10.0);
   2.194 +		    spin.set_range(-1000000.0, 1000000.0);
   2.195 +		    spin.set_numeric(true);
   2.196 +		    spin.set_value(atof(nodetextmap[active_node]->property_text().get_value().c_str()));
   2.197 +		    vbox->add(spin);
   2.198 +		    spin.show();
   2.199 +		    switch (dialog.run())
   2.200 +		      {
   2.201 +		      case Gtk::RESPONSE_NONE:
   2.202 +		      case Gtk::RESPONSE_CANCEL:
   2.203 +			break;
   2.204 +		      case Gtk::RESPONSE_ACCEPT:
   2.205 +			double new_value = spin.get_value();
   2.206 +			(*(mytab.mapstorage).nodemap_storage[nodemap_to_edit])[active_node] =
   2.207 +			  new_value;
   2.208 +			std::ostringstream ostr;
   2.209 +			ostr << new_value;
   2.210 +			nodetextmap[active_node]->property_text().set_value(ostr.str());
   2.211 +			//mapwin.updateNode(active_node);
   2.212 +			//mapwin.updateNode(Node(INVALID));
   2.213 +			propertyUpdate(Node(INVALID));
   2.214 +		      }
   2.215 +		  }
   2.216 +	      }
   2.217 +	    else
   2.218 +	      //if it was really an edge...
   2.219 +	      if(clicked_edge!=INVALID)
   2.220 +		{
   2.221 +		  // the id map is not editable
   2.222 +		  if (edgemap_to_edit == "label") return 0;
   2.223 +
   2.224 +		  //and there is activated map
   2.225 +		  if(edgetextmap[clicked_edge]->property_text().get_value()!="")
   2.226 +		    {
   2.227 +		      //activate the general variable for it
   2.228 +		      active_edge=clicked_edge;
   2.229 +
   2.230 +		      //create a dialog
   2.231 +		      Gtk::Dialog dialog("Edit value", true);
   2.232 +		      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   2.233 +		      dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   2.234 +		      Gtk::VBox* vbox = dialog.get_vbox();
   2.235 +		      Gtk::SpinButton spin(0.0, 4);
   2.236 +		      spin.set_increments(1.0, 10.0);
   2.237 +		      spin.set_range(-1000000.0, 1000000.0);
   2.238 +		      spin.set_numeric(true);
   2.239 +		      spin.set_value(atof(edgetextmap[active_edge]->property_text().get_value().c_str()));
   2.240 +		      vbox->add(spin);
   2.241 +		      spin.show();
   2.242 +		      switch (dialog.run())
   2.243 +			{
   2.244 +			case Gtk::RESPONSE_NONE:
   2.245 +			case Gtk::RESPONSE_CANCEL:
   2.246 +			  break;
   2.247 +			case Gtk::RESPONSE_ACCEPT:
   2.248 +			  double new_value = spin.get_value();
   2.249 +			  (*(mytab.mapstorage).edgemap_storage[edgemap_to_edit])[active_edge] =
   2.250 +			    new_value;
   2.251 +			  std::ostringstream ostr;
   2.252 +			  ostr << new_value;
   2.253 +			  edgetextmap[active_edge]->property_text().set_value(
   2.254 +									      ostr.str());
   2.255 +			  //mapwin.updateEdge(active_edge);
   2.256 +			  //                   mapwin.updateEdge(Edge(INVALID));
   2.257 +			  propertyUpdate(Edge(INVALID));
   2.258 +			}
   2.259 +		    }
   2.260 +		}
   2.261 +	    break;
   2.262 +	  }
   2.263 +	default:
   2.264 +	  break;
   2.265 +	}
   2.266      }
   2.267 -  }
   2.268 -  return false;  
   2.269 -}
   2.270 -
   2.271 -bool GraphDisplayerCanvas::nodeMapEditEventHandler(GdkEvent* e)
   2.272 -{
   2.273 -  if(actual_tool==NODE_MAP_EDIT)
   2.274 -  {
   2.275 -    switch(e->type)
   2.276 -    {
   2.277 -      case GDK_BUTTON_PRESS:
   2.278 -        {
   2.279 -          //for determine, whether it was a node
   2.280 -          Node clicked_node=INVALID;
   2.281 -
   2.282 -          window_to_world (e->button.x, e->button.y, clicked_x, clicked_y);
   2.283 -          active_item=(get_item_at(clicked_x, clicked_y));
   2.284 -
   2.285 -          //find the activated item between texts
   2.286 -          for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   2.287 -          {
   2.288 -            //at the same time only one can be active
   2.289 -            if(nodetextmap[i]==active_item)
   2.290 -            {
   2.291 -              clicked_node=i;
   2.292 -            }
   2.293 -          }
   2.294 -
   2.295 -          //if there was not, search for it between nodes
   2.296 -          if(clicked_node==INVALID)
   2.297 -          {
   2.298 -            for (NodeIt i((mytab.mapstorage).graph); i!=INVALID; ++i)
   2.299 -            {
   2.300 -              //at the same time only one can be active
   2.301 -              if(nodesmap[i]==active_item)
   2.302 -              {
   2.303 -                clicked_node=i;
   2.304 -              }
   2.305 -            }
   2.306 -          }
   2.307 -
   2.308 -          //if it was really a node...
   2.309 -          if(clicked_node!=INVALID)
   2.310 -          {
   2.311 -            // the id map is not editable
   2.312 -            if (nodemap_to_edit == "label") return 0;
   2.313 -
   2.314 -            //and there is activated map
   2.315 -            if(nodetextmap[clicked_node]->property_text().get_value()!="")
   2.316 -            {
   2.317 -              //activate the general variable for it
   2.318 -              active_node=clicked_node;
   2.319 -
   2.320 -              //create a dialog
   2.321 -              Gtk::Dialog dialog("Edit value", true);
   2.322 -              dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
   2.323 -              dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_ACCEPT);
   2.324 -              Gtk::VBox* vbox = dialog.get_vbox();
   2.325 -              Gtk::SpinButton spin(0.0, 4);
   2.326 -              spin.set_increments(1.0, 10.0);
   2.327 -              spin.set_range(-1000000.0, 1000000.0);
   2.328 -              spin.set_numeric(true);
   2.329 -              vbox->add(spin);
   2.330 -              spin.show();
   2.331 -              switch (dialog.run())
   2.332 -              {
   2.333 -                case Gtk::RESPONSE_NONE:
   2.334 -                case Gtk::RESPONSE_CANCEL:
   2.335 -                  break;
   2.336 -                case Gtk::RESPONSE_ACCEPT:
   2.337 -                  double new_value = spin.get_value();
   2.338 -                  (*(mytab.mapstorage).nodemap_storage[nodemap_to_edit])[active_node] =
   2.339 -                    new_value;
   2.340 -                  std::ostringstream ostr;
   2.341 -                  ostr << new_value;
   2.342 -                  nodetextmap[active_node]->property_text().set_value(
   2.343 -                      ostr.str());
   2.344 -                  //mapwin.updateNode(active_node);
   2.345 -//                   mapwin.updateNode(Node(INVALID));
   2.346 -                  propertyUpdate(Node(INVALID));
   2.347 -              }
   2.348 -            }
   2.349 -          }
   2.350 -          break;
   2.351 -        }
   2.352 -      default:
   2.353 -        break;
   2.354 -    }
   2.355 -  }
   2.356    return false;  
   2.357  }
   2.358  
     3.1 --- a/graph_displayer_canvas.cc	Mon Sep 18 16:02:20 2006 +0000
     3.2 +++ b/graph_displayer_canvas.cc	Tue Sep 19 07:43:55 2006 +0000
     3.3 @@ -177,7 +177,7 @@
     3.4  
     3.5      edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph, text_pos.x, text_pos.y, "");
     3.6      edgetextmap[i]->property_fill_color().set_value("darkgreen");
     3.7 -    edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::edgeMapEditEventHandler), false);
     3.8 +    edgetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
     3.9      edgetextmap[i]->raise_to_top();
    3.10    }
    3.11  
    3.12 @@ -206,7 +206,7 @@
    3.13      nodetextmap[i]=new Gnome::Canvas::Text(displayed_graph,
    3.14          text_pos.x, text_pos.y, "");
    3.15      nodetextmap[i]->property_fill_color().set_value("darkblue");
    3.16 -    nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::nodeMapEditEventHandler), false);
    3.17 +    nodetextmap[i]->signal_event().connect(sigc::mem_fun(*this, &GraphDisplayerCanvas::mapEditEventHandler), false);
    3.18      nodetextmap[i]->raise_to_top();
    3.19    }
    3.20  
     4.1 --- a/graph_displayer_canvas.h	Mon Sep 18 16:02:20 2006 +0000
     4.2 +++ b/graph_displayer_canvas.h	Tue Sep 19 07:43:55 2006 +0000
     4.3 @@ -43,6 +43,7 @@
     4.4        virtual void draw() = 0;
     4.5        virtual void setLineWidth(int) = 0;
     4.6        virtual void setFillColor(Gdk::Color) = 0;
     4.7 +      virtual Gnome::Canvas::Item * getLine() = 0;
     4.8    };
     4.9  
    4.10    ///Edge displayer class
    4.11 @@ -97,6 +98,8 @@
    4.12  
    4.13        void setLineWidth(int);
    4.14        void setFillColor(Gdk::Color);
    4.15 +
    4.16 +      Gnome::Canvas::Item * getLine() { return (Gnome::Canvas::Item *)(&line); };
    4.17    };
    4.18  
    4.19    class LoopEdge : public EdgeBase
    4.20 @@ -109,6 +112,7 @@
    4.21        void draw();
    4.22        void setLineWidth(int);
    4.23        void setFillColor(Gdk::Color);
    4.24 +      Gnome::Canvas::Item * getLine() { return (Gnome::Canvas::Item *)(&line); };
    4.25    };
    4.26  
    4.27    ///Type of canvas, on which the graph is drawn
    4.28 @@ -259,10 +263,8 @@
    4.29    bool createEdgeEventHandler(GdkEvent*);
    4.30    ///event handler for the case when eraser-tool is active
    4.31    bool eraserEventHandler(GdkEvent*);
    4.32 -  ///event handler for the case when edge map editor tool is active
    4.33 -  bool edgeMapEditEventHandler(GdkEvent*);
    4.34 -  ///event handler for the case when node map editor tool is active
    4.35 -  bool nodeMapEditEventHandler(GdkEvent*);
    4.36 +  ///event handler for the case when map editor tool is active
    4.37 +  bool mapEditEventHandler(GdkEvent*);
    4.38  
    4.39  public:
    4.40    ///Moves the text to new place
     5.1 --- a/main_win.cc	Mon Sep 18 16:02:20 2006 +0000
     5.2 +++ b/main_win.cc	Tue Sep 19 07:43:55 2006 +0000
     5.3 @@ -26,8 +26,6 @@
     5.4        2328, gui_icons_delete);
     5.5    Glib::RefPtr<Gdk::Pixbuf> p_editlink_pixbuf = Gdk::Pixbuf::create_from_inline(
     5.6        2328, gui_icons_editlink);
     5.7 -  Glib::RefPtr<Gdk::Pixbuf> p_editnode_pixbuf = Gdk::Pixbuf::create_from_inline(
     5.8 -      2328, gui_icons_editnode);
     5.9    Glib::RefPtr<Gdk::Pixbuf> p_newmap_pixbuf = Gdk::Pixbuf::create_from_inline(
    5.10        2328, gui_icons_newmap);
    5.11  
    5.12 @@ -61,12 +59,6 @@
    5.13    editlink_icon_set.add_source(editlink_icon_source);
    5.14    p_icon_factory->add(Gtk::StockID("gd-editlink"), editlink_icon_set);
    5.15  
    5.16 -  Gtk::IconSource editnode_icon_source;
    5.17 -  editnode_icon_source.set_pixbuf(p_editnode_pixbuf);
    5.18 -  Gtk::IconSet editnode_icon_set;
    5.19 -  editnode_icon_set.add_source(editnode_icon_source);
    5.20 -  p_icon_factory->add(Gtk::StockID("gd-editnode"), editnode_icon_set);
    5.21 -
    5.22    Gtk::IconSource newmap_icon_source;
    5.23    newmap_icon_source.set_pixbuf(p_newmap_pixbuf);
    5.24    Gtk::IconSet newmap_icon_set;
    5.25 @@ -125,8 +117,6 @@
    5.26  
    5.27    ag->add( Gtk::RadioAction::create(tool_group, "EditEdgeMap", Gtk::StockID("gd-editlink"), _("Edit edge map")),
    5.28        sigc::bind( sigc::mem_fun ( *this, &MainWin::changeEditorialTool ), 4) );
    5.29 -  ag->add( Gtk::RadioAction::create(tool_group, "EditNodeMap", Gtk::StockID("gd-editnode"), _("Edit node map")),
    5.30 -      sigc::bind( sigc::mem_fun ( *this, &MainWin::changeEditorialTool ), 5) );
    5.31  
    5.32    ag->add( Gtk::Action::create("AddMap", Gtk::StockID("gd-newmap")),
    5.33        sigc::mem_fun ( *this , &MainWin::createNewMapWin ) );
    5.34 @@ -180,7 +170,6 @@
    5.35        "    <toolitem action='CreateEdge' />"
    5.36        "    <toolitem action='EraseItem' />"
    5.37        "    <toolitem action='EditEdgeMap' />"
    5.38 -      "    <toolitem action='EditNodeMap' />"
    5.39        "    <separator />"
    5.40        "    <toolitem action='AddMap' />"
    5.41        "  </toolbar>"