Code

Added connector graph layout functionality
authortgdwyer <tgdwyer@users.sourceforge.net>
Mon, 13 Feb 2006 02:00:14 +0000 (02:00 +0000)
committertgdwyer <tgdwyer@users.sourceforge.net>
Mon, 13 Feb 2006 02:00:14 +0000 (02:00 +0000)
configure.ac
share/icons/icons.svg
src/Makefile.am
src/Makefile_insert
src/graphlayout/Makefile_insert [new file with mode: 0644]
src/graphlayout/graphlayout.cpp [new file with mode: 0644]
src/graphlayout/graphlayout.h [new file with mode: 0644]
src/graphlayout/makefile [new file with mode: 0644]
src/libavoid/connector.cpp
src/ui/dialog/align-and-distribute.cpp
src/ui/dialog/align-and-distribute.h

index b0ce823c14b8175a900424049ac0ec01d2ec2e28..17b753c6febda506d3647f44e962992fce5a2247 100644 (file)
@@ -537,6 +537,13 @@ if test "$enable_osxapp" = "yes"; then
    AC_DEFINE(ENABLE_OSX_APP_LOCATIONS,,[Build with OSX .app data dir paths?])
 fi
 
+dnl ******************************
+dnl   Boost graph library is required for graphlayout functions
+dnl ******************************
+AC_CHECK_HEADER([boost/graph/adjacency_list.hpp],
+                [AC_DEFINE([HAVE_BOOST_GRAPH_LIB],[],[Will enable connector network layout])],
+                [AC_MSG_WARN([Boost graph lib not found, can't include connector network layout functionality.])])
+
 dnl ******************************
 dnl   Reported by autoscan
 dnl ******************************
index e2f7118a8fbf7a0ad78def40984637b7b2377836..f29f45c7620ed68a1c396135f1b84bc05fb0e99e 100644 (file)
@@ -14,7 +14,7 @@
    height="320"
    sodipodi:docname="icons.svg"
    inkscape:version="0.43+devel"
-   sodipodi:docbase="/home/rws/inkscape/share/icons">
+   sodipodi:docbase="/home/dwyer/devel/inkscape/share/icons">
   <defs
      id="defs3">
     <marker
      showgrid="true"
      snaptogrid="false"
      gridtolerance="1.02pt"
-     inkscape:zoom="0.74316288"
-     inkscape:cx="548.32181"
-     inkscape:cy="177.66989"
-     inkscape:window-width="821"
-     inkscape:window-height="894"
-     inkscape:window-x="260"
-     inkscape:window-y="26"
+     inkscape:zoom="3.2920645"
+     inkscape:cx="1014.4803"
+     inkscape:cy="134.90777"
+     inkscape:window-width="1272"
+     inkscape:window-height="948"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
      snaptoguides="true"
      pagecolor="#e8e8e4"
@@ -8259,4 +8259,144 @@ http://www.inkscape.org/</dc:description>
        width="1500"
        height="320" />
   </g>
+  <g
+     id="graph_layout"
+     transform="matrix(0.871684,0,0,1.153001,84.37157,-57.45528)">
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1009.2604"
+       x="182.68007"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1325"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1044.4941"
+       x="181.72984"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1327"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1037.2839"
+       x="171.92137"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1329"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1044.7812"
+       x="163.17259"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1331"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1007.1793"
+       x="170.92931"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1333"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1026.1293"
+       x="172.72229"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1335"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1017.0864"
+       x="165.02521"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1337"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       transform="matrix(0,1,-1,0,0,0)"
+       ry="10.389093"
+       rx="9.5770855"
+       y="-1020.1285"
+       x="183.54044"
+       height="5.0466266"
+       width="5.1440129"
+       id="rect1339"
+       style="fill:#0686f6;fill-opacity:0.67582415;stroke:#000000;stroke-width:0.34266412;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1337"
+       inkscape:connection-start="#rect1333"
+       inkscape:connector-type="polyline"
+       id="path8205"
+       d="M 1007.3507,171.89545 L 1011.8685,169.20308"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1335"
+       inkscape:connection-start="#rect1337"
+       inkscape:connector-type="polyline"
+       id="path8207"
+       d="M 1017.2578,169.89084 L 1020.9113,173.00067"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1329"
+       inkscape:connection-start="#rect1335"
+       inkscape:connector-type="polyline"
+       id="path8209"
+       d="M 1026.3006,175.10082 L 1032.066,174.68686"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1331"
+       inkscape:connection-start="#rect1329"
+       inkscape:connector-type="polyline"
+       id="path8211"
+       d="M 1037.1115,171.75004 L 1039.907,168.48794"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1327"
+       inkscape:connection-start="#rect1329"
+       inkscape:connector-type="polyline"
+       id="path8213"
+       d="M 1036.7772,177.23672 L 1039.9542,181.55851"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1339"
+       inkscape:connection-start="#rect1335"
+       inkscape:connector-type="polyline"
+       id="path8215"
+       d="M 1022.0842,178.03764 L 1019.1269,183.3691"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1325"
+       inkscape:connection-start="#rect1339"
+       inkscape:connector-type="polyline"
+       id="path8217"
+       d="M 1014.9105,185.89912 L 1009.4317,185.4654"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect1333"
+       inkscape:connection-start="#rect1325"
+       inkscape:connector-type="polyline"
+       id="path8219"
+       d="M 1006.2512,182.50874 L 1005.1419,176.24465"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+  </g>
 </svg>
index 73e6deb367d1a66e938c877a50ad947eac4d085a..6ac221a1abad30406aec72c397a280081e04294c 100644 (file)
@@ -43,6 +43,7 @@ include libnrtype/Makefile_insert
 include libavoid/Makefile_insert
 include livarot/Makefile_insert
 include removeoverlap/Makefile_insert
+include graphlayout/Makefile_insert
 include svg/Makefile_insert
 include utest/Makefile_insert
 include widgets/Makefile_insert
@@ -85,6 +86,7 @@ noinst_LIBRARIES =    \
        libavoid/libavoid.a     \
        livarot/libvarot.a      \
        removeoverlap/libremoveoverlap.a        \
+       graphlayout/libgraphlayout.a    \
        svg/libspsvg.a  \
        widgets/libspwidgets.a  \
        trace/libtrace.a  \
index 3952e8cf5a2159cb06afbae96011d3f40cd17c81..302bd8089f3071e75acf2d4bd584d4aca11759f7 100644 (file)
@@ -259,6 +259,7 @@ inkscape_private_libs =     \
        ui/view/libuiview.a     \
        ui/libui.a              \
        ui/widget/libuiwidget.a \
+       graphlayout/libgraphlayout.a    \
        removeoverlap/libremoveoverlap.a                \
        extension/libextension.a        \
        extension/implementation/libimplementation.a    \
diff --git a/src/graphlayout/Makefile_insert b/src/graphlayout/Makefile_insert
new file mode 100644 (file)
index 0000000..fc49074
--- /dev/null
@@ -0,0 +1,10 @@
+## Makefile.am fragment sourced by src/Makefile.am.
+
+graphlayout/all: graphlayout/libgraphlayout.a
+
+graphlayout/clean:
+       rm -f graphlayout/libgraphlayout.a $(graphlayout_libgraphlayout_a_OBJECTS)
+
+graphlayout_libgraphlayout_a_SOURCES = \
+       graphlayout/graphlayout.cpp     \
+       graphlayout/graphlayout.h
diff --git a/src/graphlayout/graphlayout.cpp b/src/graphlayout/graphlayout.cpp
new file mode 100644 (file)
index 0000000..9828e22
--- /dev/null
@@ -0,0 +1,147 @@
+/** \file
+ * Interface between Inkscape code (SPItem) and graphlayout functions.
+ */
+/*
+* Authors:
+*   Tim Dwyer <tgdwyer@gmail.com>
+*
+* Copyright (C) 2005 Authors
+*
+* Released under GNU GPL.  Read the file 'COPYING' for more information.
+*/
+#include "graphlayout/graphlayout.h"
+#include <iostream>
+#include <config.h>
+
+#ifdef HAVE_BOOST_GRAPH_LIB
+#include "sp-item.h"
+#include "sp-item-transform.h"
+#include "sp-conn-end-pair.h"
+#include "conn-avoid-ref.h"
+#include "libavoid/connector.h"
+#include <boost/graph/kamada_kawai_spring_layout.hpp>
+#include <boost/graph/circle_layout.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/simple_point.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <string.h>
+
+using namespace boost;
+// create a typedef for the Graph type
+typedef adjacency_list<vecS, vecS, undirectedS, no_property, 
+       property<edge_weight_t, double> > Graph;
+typedef property_map<Graph, edge_weight_t>::type WeightMap;
+typedef graph_traits<Graph>::vertex_descriptor Vertex;
+typedef std::vector<simple_point<double> > PositionVec;
+typedef iterator_property_map<PositionVec::iterator, property_map<Graph, vertex_index_t>::type> PositionMap;
+#endif // HAVE_BOOST_GRAPH_LIB
+
+/**
+* Takes a list of inkscape items, extracts the graph defined by 
+* connectors between them, and uses graph layout techniques to find
+* a nice layout
+*/
+void graphlayout(GSList const *const items) {
+       if(!items) {
+               return;
+       }
+#ifdef HAVE_BOOST_GRAPH_LIB
+
+
+       using Inkscape::Util::GSListConstIterator;
+       std::list<SPItem *> selected;
+       selected.insert<GSListConstIterator<SPItem *> >(selected.end(), items, NULL);
+       if (selected.empty()) return;
+       int n=selected.size();
+
+       //Check 2 or more selected objects
+       if (n < 2) return;
+
+       Graph g;
+
+       std::cout<<"Building graph with "<<n<<" nodes"<<std::endl;
+       double minX=DBL_MAX, minY=DBL_MAX, maxX=-DBL_MAX, maxY=-DBL_MAX;
+
+       std::map<std::string,Vertex> nodelookup;
+       for (std::list<SPItem *>::iterator it(selected.begin());
+               it != selected.end();
+               ++it)
+       {
+               SPItem *u=*it;
+               std::cout<<"id:"<<u->id<<std::endl;
+               if(strncmp(u->id,"path",4)) {
+                       nodelookup[u->id]=add_vertex(g);
+               }
+       }
+       WeightMap weightmap=get(edge_weight, g);
+       std::cout<<"Added vertices: Graph has |V|="<<num_vertices(g)<<std::endl;
+
+       NR::Point const gap(0, 0);
+       int i=0;
+       for (std::list<SPItem *>::iterator it(selected.begin());
+               it != selected.end();
+               ++it)
+       {
+               using NR::X; using NR::Y;
+               SPItem *itu=*it;
+               Vertex u=nodelookup[itu->id];
+               GSList *nlist=itu->avoidRef->getAttachedConnectors(Avoid::ConnRef::runningFrom);
+               std::list<SPItem *> neighbours;
+               neighbours.insert<GSListConstIterator<SPItem *> >(neighbours.end(),nlist,NULL);
+               std::cout<<"  Node "<<itu->id<<" has "<<neighbours.size()<<" neighbours"<<std::endl;
+               for (std::list<SPItem *>::iterator ne(neighbours.begin());
+                               ne != neighbours.end();
+                               ++ne) {
+                       
+                       SPItem *itv=*ne;
+                       std::cout<<"neighbour: "<<itv->id<<std::endl;
+                       Vertex v=nodelookup[itv->id];
+                       std::cout<<"    Neighbour: "<<v;
+                       Graph::edge_descriptor e; bool inserted;
+                       tie(e, inserted)=add_edge(u,v,g);
+                       weightmap[e]=1.0;
+               }
+               if(nlist) {
+                       g_slist_free(nlist);
+               }
+               NR::Rect const item_box(sp_item_bbox_desktop(*it));
+                       
+               NR::Point ll(item_box.min());
+               minX=std::min(ll[0],minX);
+               minY=std::min(ll[1],minY);
+               NR::Point ur(item_box.max());
+               maxX=std::max(ur[0],maxX);
+               maxY=std::max(ur[1],maxY);
+       }
+       double width=maxX-minX;
+       double height=maxY-minY;
+       std::cout<<"Graph has |V|="<<num_vertices(g)<<" Width="<<width<<" Height="<<height<<std::endl;
+       PositionVec position_vec(num_vertices(g));
+       PositionMap position(position_vec.begin(), get(vertex_index, g));
+       write_graphviz(std::cout, g);
+       circle_graph_layout(g, position, width/2.0);
+       kamada_kawai_spring_layout(g, position, weightmap, side_length(width));
+
+       graph_traits<Graph>::vertex_iterator vi, vi_end;
+       i=0;
+       for (std::list<SPItem *>::iterator it(selected.begin());
+               it != selected.end();
+               ++it)
+       {
+               SPItem *u=*it;
+               if(strncmp(u->id,"path",4)) {
+                       NR::Rect const item_box(sp_item_bbox_desktop(u));
+                       NR::Point const curr(item_box.midpoint());
+                       NR::Point const dest(minX+width/2.0+position[nodelookup[u->id]].x,
+                                       minY+height/2.0+position[nodelookup[u->id]].y);
+                       sp_item_move_rel(u, NR::translate(dest - curr));
+               }
+       }
+#else
+       std::cout<<"Connector network layout not available!  Install boost graph library and recompile to enable."<<std::endl;
+#endif // HAVE_BOOST_GRAPH_LIB
+}
diff --git a/src/graphlayout/graphlayout.h b/src/graphlayout/graphlayout.h
new file mode 100644 (file)
index 0000000..e37f4c4
--- /dev/null
@@ -0,0 +1,17 @@
+/**
+ * \brief graph layout functions
+ *
+ * Authors:
+ *   Tim Dwyer <tgdwyer@gmail.com>
+ *
+ * Copyright (C) 2005 Authors
+ *
+ * Released under GNU GPL.  Read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_GRAPHLAYOUT_H
+#define SEEN_GRAPHLAYOUT_H
+#include "util/glib-list-iterators.h"
+
+void graphlayout(GSList const *const items);
+#endif // SEEN_GRAPHLAYOUT_H
diff --git a/src/graphlayout/makefile b/src/graphlayout/makefile
new file mode 100644 (file)
index 0000000..5d8ac90
--- /dev/null
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+
+
+# Explicit so that it's the default rule.
+all:
+       cd .. && $(MAKE) graphlayout/all
+
+clean %.a %.o:
+       cd .. && $(MAKE) graphlayout/$@
+
+.PHONY: all clean
+
+OBJEXT = o
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
index 04bf7aaada6b573ad8479174a4f263d343b934f0..06a0cd4aae24e81ab9adba6db33b30ff60336a26 100644 (file)
@@ -428,10 +428,10 @@ void attachedToShape(IntList &conns, const unsigned int shapeId,
     ConnRefList::iterator fin = connRefs.end();
     for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i) {
         if ((type & ConnRef::runningTo) && ((*i)->_dstId == shapeId)) {
-            conns.push_back((*i)->_id);
+            conns.push_back((*i)->_srcId);
         }
         else if ((type & ConnRef::runningFrom) && ((*i)->_srcId == shapeId)) {
-            conns.push_back((*i)->_id);
+            conns.push_back((*i)->_dstId);
         }
     }
 }
index 262aa690bbda854a36e51bcb465616a0a0ba68d7..35ee7b806389536c3f176e5aff7d7a8069301795 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "dialogs/unclump.h"
 #include "removeoverlap/removeoverlap.h"
+#include "graphlayout/graphlayout.h"
 
 #include <gtkmm/spinbutton.h>
 
@@ -487,6 +488,35 @@ private :
     }
 };
 
+class ActionGraphLayout : public Action {
+public:
+    ActionGraphLayout(Glib::ustring const &id,
+                         Glib::ustring const &tiptext,
+                         guint row,
+                         guint column,
+                         AlignAndDistribute &dialog) :
+        Action(id, tiptext, row, column + 4,
+               dialog.graphLayout_table(), dialog.tooltips(), dialog)
+    {}
+
+private :
+    virtual void on_button_click()
+    {
+        if (!SP_ACTIVE_DESKTOP) return;
+
+        // see comment in ActionAlign above
+        int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+        prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+        graphlayout(SP_DT_SELECTION(SP_ACTIVE_DESKTOP)->itemList());
+
+        // restore compensation setting
+        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+        sp_document_done(SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP));
+    }
+};
+
 class ActionUnclump : public Action {
 public :
     ActionUnclump(const Glib::ustring &id,
@@ -717,10 +747,12 @@ AlignAndDistribute::AlignAndDistribute()
       _alignFrame(_("Align")),
       _distributeFrame(_("Distribute")),
       _removeOverlapFrame(_("Remove overlaps")),
+      _graphLayoutFrame(_("Connector network layout")),
       _nodesFrame(_("Nodes")),
       _alignTable(2, 6, true),
       _distributeTable(3, 6, true),
       _removeOverlapTable(1, 5, false),
+      _graphLayoutTable(1, 5, false),
       _nodesTable(1, 4, true),
       _anchorLabel(_("Relative to: "))
 {
@@ -814,6 +846,10 @@ AlignAndDistribute::AlignAndDistribute()
     addRemoveOverlapsButton("remove_overlaps",
                             _("Move objects as little as possible so that their bounding boxes do not overlap"),
                             0, 0);
+    //Graph Layout
+    addGraphLayoutButton("graph_layout",
+                            _("Nicely arrange selected connector network"),
+                            0, 0);
 
     //Node Mode buttons
     addNodeButton("node_halign",
@@ -851,6 +887,7 @@ AlignAndDistribute::AlignAndDistribute()
     _alignFrame.add(_alignBox);
     _distributeFrame.add(_distributeTable);
     _removeOverlapFrame.add(_removeOverlapTable);
+    _graphLayoutFrame.add(_graphLayoutTable);
     _nodesFrame.add(_nodesTable);
 
     // Top level vbox
@@ -862,6 +899,7 @@ AlignAndDistribute::AlignAndDistribute()
     vbox->pack_start(_alignFrame, true, true);
     vbox->pack_start(_distributeFrame, true, true);
     vbox->pack_start(_removeOverlapFrame, true, true);
+    vbox->pack_start(_graphLayoutFrame, true, true);
     vbox->pack_start(_nodesFrame, true, true);
 
     //Connect to the global tool change signal
@@ -908,6 +946,7 @@ void AlignAndDistribute::setMode(bool nodeEdit)
     ((_alignFrame).*(mSel))();
     ((_distributeFrame).*(mSel))();
     ((_removeOverlapFrame).*(mSel))();
+    ((_graphLayoutFrame).*(mSel))();
     ((_nodesFrame).*(mNode))();
 
 }
@@ -950,6 +989,15 @@ void AlignAndDistribute::addRemoveOverlapsButton(const Glib::ustring &id, const
         );
 }
 
+void AlignAndDistribute::addGraphLayoutButton(const Glib::ustring &id, const Glib::ustring tiptext,
+                                      guint row, guint col)
+{
+    _actionList.push_back(
+        new ActionGraphLayout(
+            id, tiptext, row, col, *this)
+        );
+}
+
 void AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
                                       guint row, guint col)
 {
index 35ca3c7c3119dd069469ce5f208716759d01fb69..69fc176736aae8a6785114d047436574e0ff8520 100644 (file)
@@ -58,6 +58,7 @@ public:
     Gtk::Table &align_table(){return _alignTable;}
     Gtk::Table &distribute_table(){return _distributeTable;}
     Gtk::Table &removeOverlap_table(){return _removeOverlapTable;}
+    Gtk::Table &graphLayout_table(){return _graphLayoutTable;}
     Gtk::Table &nodes_table(){return _nodesTable;}
     Gtk::Tooltips &tooltips(){return _tooltips;}
 
@@ -81,6 +82,9 @@ protected:
     void addRemoveOverlapsButton(const Glib::ustring &id,
                         const Glib::ustring tiptext,
                         guint row, guint col);
+    void addGraphLayoutButton(const Glib::ustring &id,
+                        const Glib::ustring tiptext,
+                        guint row, guint col);
     void addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext, 
                         guint row, guint col);
     void addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext, 
@@ -89,8 +93,8 @@ protected:
                            guint row, guint col, Gtk::Table &table, NR::Dim2 orientation, bool distribute);
 
     std::list<Action *> _actionList;
-    Gtk::Frame _alignFrame, _distributeFrame, _removeOverlapFrame, _nodesFrame;
-    Gtk::Table _alignTable, _distributeTable, _removeOverlapTable, _nodesTable;
+    Gtk::Frame _alignFrame, _distributeFrame, _removeOverlapFrame, _graphLayoutFrame, _nodesFrame;
+    Gtk::Table _alignTable, _distributeTable, _removeOverlapTable, _graphLayoutTable, _nodesTable;
     Gtk::HBox _anchorBox;
     Gtk::VBox _alignBox;
     Gtk::Label _anchorLabel;