[dia] OGDF based automatic layout plug-in for Dia



commit 8a9c2129ca7c8574c2e5eab1a2dc48218b64860c
Author: Hans Breuer <hans breuer org>
Date:   Mon Oct 3 17:08:24 2011 +0200

    OGDF based automatic layout plug-in for Dia
    
    Providing a bunch of automatic graph layout algorithms
    with based on OGDF (www.ogdf.net)
    
    See plug-ins/layout/readme.txt for build details.

 plug-ins/layout/layout.cpp      |  379 ++++++++++++++++++++++++++++++++++
 plug-ins/layout/makefile.msc    |  429 +++++++++++++++++++++++++++++++++++++++
 plug-ins/layout/ogdf-simple.cpp |  380 ++++++++++++++++++++++++++++++++++
 plug-ins/layout/ogdf-simple.h   |   71 +++++++
 plug-ins/layout/readme.txt      |   41 ++++
 plug-ins/makefile.msc           |    9 +-
 6 files changed, 1308 insertions(+), 1 deletions(-)
---
diff --git a/plug-ins/layout/layout.cpp b/plug-ins/layout/layout.cpp
new file mode 100644
index 0000000..e397775
--- /dev/null
+++ b/plug-ins/layout/layout.cpp
@@ -0,0 +1,379 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * layout.cpp -  registeration and binding of OGDF layout algoritms as Dia plug-in
+ * Copyright (c) 2011 Hans Breuer <hans breuer org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include "intl.h"
+#include "message.h"
+#include "filter.h"
+#include "plug-ins.h"
+#include "object.h"
+#include "properties.h"
+#include "propinternals.h"
+
+#include "diagram.h"
+#include "connectionpoint_ops.h"
+
+#include "ogdf-simple.h"
+
+#include <vector>
+
+static gboolean
+maybe_edge (DiaObject *object)
+{
+  int i, nhc = 0;
+
+  for (i = 0; i < object->num_handles; ++i) {
+    if (object->handles[i]->connect_type == HANDLE_CONNECTABLE) {
+      ++nhc;
+      if (nhc > 1)
+        return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/*!
+ * Translate from various Dia point representation to OGDF 'bends',
+ * the latter not containing the first and last point I think.
+ */
+static int
+_obj_get_bends (DiaObject *obj, std::vector<double>& coords)
+{
+  Property *prop = NULL;
+  
+  coords.resize(0);
+  // no need to ask for Standard - Line: start_point, end_point
+  // we always drop the very first and last point
+  if ((prop = object_prop_by_name(obj, "orth_points")) != NULL ||
+      (prop = object_prop_by_name(obj, "poly_points")) != NULL) {
+    PointarrayProperty *ptp = (PointarrayProperty *)prop;
+    int num = ptp->pointarray_data->len;
+
+    for (int i = 1; i < num-1; ++i) {
+      Point *pt = &g_array_index(ptp->pointarray_data, Point, i);
+      coords.push_back (pt->x);
+      coords.push_back (pt->y);
+    }
+  } else if ((prop = object_prop_by_name(obj, "bez_points")) != NULL) {
+    BezPointarrayProperty *ptp = (BezPointarrayProperty *)prop;
+    int num = ptp->bezpointarray_data->len;
+    
+    for (int i = 1; i < num-1; ++i) {
+      BezPoint *bp = &g_array_index(ptp->bezpointarray_data, BezPoint, i);
+
+      // TODO: better conversion from polyline to bezierline
+      if (bp->type == BezPoint::BEZ_CURVE_TO) {
+        coords.push_back (bp->p3.x);
+        coords.push_back (bp->p3.y);
+      } else {
+        coords.push_back (bp->p1.x);
+        coords.push_back (bp->p1.y);
+      }
+    }
+  }
+
+  if (prop)
+    prop->ops->free(prop);
+  return coords.size();
+}
+static ObjectChange *
+_obj_set_bends (DiaObject *obj, std::vector<double>& coords)
+{
+  Property *prop = NULL;
+  
+  if ((prop = object_prop_by_name(obj, "poly_points")) != NULL) {
+    PointarrayProperty *ptp = (PointarrayProperty *)prop;
+    int num = ptp->pointarray_data->len;
+    Point last  = g_array_index(ptp->pointarray_data, Point, num-1);
+    // we keep the first and last point (the connected ones) and overwrite the rest
+    num = coords.size()/2+2;
+
+    g_array_set_size(ptp->pointarray_data, num);
+    for (int i = 1; i < num-1; ++i) {
+      Point *pt = &g_array_index(ptp->pointarray_data, Point, i);
+      pt->x = coords[(i-1)*2];
+      pt->y = coords[(i-1)*2+1];
+    }
+    g_array_index(ptp->pointarray_data, Point, num-1) = last;
+  } else if ((prop = object_prop_by_name(obj, "orth_points")) != NULL) {
+    PointarrayProperty *ptp = (PointarrayProperty *)prop;
+    int num = ptp->pointarray_data->len;
+    Point last  = g_array_index(ptp->pointarray_data, Point, num-1);
+    // we keep the first and last point (the connected ones) and overwrite the rest
+    num = coords.size()/2+2;
+
+    // there must be at least 3 points with an orthconn, so we may have to create one
+    // TODO: also maintain the orthogonality?
+    if (num == 2) {
+      Point first  = g_array_index(ptp->pointarray_data, Point, 0);
+      Point pt = { (first.x + last.x) / 2, (first.y + last.y) / 2 };
+      ++num;
+      g_array_set_size(ptp->pointarray_data, num);
+      g_array_index(ptp->pointarray_data, Point, num-2) = pt;
+    } else {
+      g_array_set_size(ptp->pointarray_data, num);
+      for (int i = 1; i < num-1; ++i) {
+	Point *pt = &g_array_index(ptp->pointarray_data, Point, i);
+	pt->x = coords[(i-1)*2];
+	pt->y = coords[(i-1)*2+1];
+      }
+    }
+    g_array_index(ptp->pointarray_data, Point, num-1) = last;
+  } else if ((prop = object_prop_by_name(obj, "bez_points")) != NULL) {
+    BezPointarrayProperty *ptp = (BezPointarrayProperty *)prop;
+    int num = ptp->bezpointarray_data->len;
+    BezPoint last = g_array_index(ptp->bezpointarray_data, BezPoint, num-1);
+
+    // we keep the first and last point (the connected ones) and overwrite the rest
+    num = coords.size()/2+1;
+    if (num == 1) {
+      // still want to have two points - a straight line
+      g_array_set_size(ptp->bezpointarray_data, 2);
+      last.p1 = last.p3;
+      last.p2 = g_array_index(ptp->bezpointarray_data, BezPoint, 0).p1;
+      g_array_index(ptp->bezpointarray_data, BezPoint, 1) = last;
+    } else {
+      // the bends are used for control points ...
+      Point p1;
+
+      p1.x = coords[0];
+      p1.y = coords[1];
+      g_array_set_size(ptp->bezpointarray_data, num);
+      for (int i = 1; i < num-1; ++i) {
+	BezPoint *bp = &g_array_index(ptp->bezpointarray_data, BezPoint, i);
+
+	// TODO: better conversion from polyline to bezierline?
+	bp->type = BezPoint::BEZ_CURVE_TO;
+	bp->p1 = p1;
+	bp->p2 = p1;
+	// ... and an extra point on every segment center
+	bp->p3.x = (p1.x + coords[i*2]) / 2;
+	bp->p3.y = (p1.y + coords[i*2+1]) / 2;
+	// next control point
+	p1.x = coords[i*2];
+	p1.y = coords[i*2+1];
+      }
+      last.type = BezPoint::BEZ_CURVE_TO;
+      last.p1 = p1;
+      last.p2 = p1;
+      g_array_index(ptp->bezpointarray_data, BezPoint, num-1) = last;
+    }
+  }
+
+  if (prop) {
+    GPtrArray *props = prop_list_from_single (prop);
+    return object_apply_props (obj, props);
+  }
+  return NULL;
+}
+
+static ObjectChange *
+layout_callback (DiagramData *data,
+                 const gchar *filename,
+                 guint flags, /* further additions */
+                 void *user_data)
+{
+  ObjectChange *changes = NULL;
+  GList *nodes = NULL, *edges = NULL, *list;
+
+  /* from the selection create two lists */
+  list = data_get_sorted_selected (data);
+  while (list) {
+    DiaObject *o = (DiaObject *)list->data;
+    if (!maybe_edge (o))
+      nodes = g_list_append (nodes, o);
+    //FIXME: neither 1 nor num_handles-1 is guaranteed to be the second connection
+    // it entirely depends on the objects implementation
+    else if (   o->num_handles > 1 && o->handles[0]->connected_to 
+             && (o->handles[1]->connected_to || o->handles[o->num_handles-1]->connected_to))
+      edges = g_list_append (edges, o);
+    list = g_list_next(list);
+  }
+  if (g_list_length (edges) < 1 || g_list_length (nodes) < 2) {
+    message_warning (_("Please select edges and nodes to layout."));
+  } else {
+#ifdef HAVE_OGDF
+    IGraph *g = CreateGraph ();
+#else
+    IGraph *g = NULL;
+#endif
+    if (!g)
+      message_error (_("Graph creation failed"));
+    else {
+      std::vector<double> coords;
+
+      /* transfer nodes and edges */
+      for (list = nodes; list != NULL; list = g_list_next(list)) {
+        DiaObject *o = (DiaObject *)list->data;
+        const Rectangle *bbox = dia_object_get_bounding_box (o);
+        g->AddNode (bbox->left, bbox->top, bbox->right, bbox->bottom);
+      }
+      for (list = edges; list != NULL; list = g_list_next(list)) {
+        DiaObject *o = (DiaObject *)list->data;
+	DiaObject *src = o->handles[0]->connected_to->object;
+	// see above: there is no guarantee ...
+	DiaObject *dst = o->handles[1]->connected_to ?
+	  o->handles[1]->connected_to->object : o->handles[o->num_handles-1]->connected_to->object;
+
+	if (_obj_get_bends (o, coords))
+          g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), &coords[0], coords.size());
+	else
+          g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), NULL, 0);
+      }
+      IGraph::eResult res;
+      if ((res = g->Layout ((const char*)user_data)) != IGraph::SUCCESS) {
+	const char *sErr;
+	switch (res) {
+	case IGraph::NO_MODULE : sErr = _("No such module."); break;
+	case IGraph::OUT_OF_MEMORY : sErr = _("Out of memory."); break;
+	case IGraph::NO_TREE: sErr = _("Not a tree."); break;
+	case IGraph::NO_FOREST: sErr = _("Not a forest."); break;
+	case IGraph::FAILED_ALGORITHM: sErr = _("Failed algorithm."); break;
+	case IGraph::FAILED_PRECONDITION: sErr = _("Failed precondition."); break;
+	case IGraph::CRASHED : sErr = _("OGDF crashed."); break;
+	default : sErr = _("Unknown reason"); break;
+	}
+        message_warning (_("Layout '%s' failed.\n%s"), (const char*)user_data, sErr);
+      } else {
+        changes = change_list_create ();
+	/* transfer back information */
+	int n;
+	for (n = 0, list = nodes; list != NULL; list = g_list_next (list), ++n) {
+	  Point pt;
+	  if (g->GetNodePosition (n, &pt.x, &pt.y)) {
+	    DiaObject *o = (DiaObject *)list->data;
+	    GPtrArray *props = g_ptr_array_new ();
+	    
+	    //FIXME: can't use "obj_pos", it is not read in usual update_data impementations
+	    // "elem_corner" will only work for Element derived classes, but that covers most
+	    // of the cases here ...
+	    prop_list_add_point (props, "elem_corner", &pt);
+	    change_list_add (changes, object_apply_props (o, props));
+	  }
+	}
+	// first update to reuse the connected points
+	diagram_update_connections_selection(DIA_DIAGRAM (data));
+	/* use edge bends, if any */
+	int e;
+	for (e = 0, list = edges; list != NULL; list = g_list_next (list), ++e) {
+          DiaObject *o = (DiaObject *)list->data;
+	  // number of bends / 2 is the number of points
+	  int n = g->GetEdgeBends (e, NULL, 0);
+	  if (n >= 0) { // with 0 it is just a reset of the exisiting line
+	    try {
+	      coords.resize (n);
+	    } catch (std::bad_alloc& ex) {
+	      g_warning (ex.what());
+	      continue;
+	    }
+	    g->GetEdgeBends (e, &coords[0], n);
+	    change_list_add (changes, _obj_set_bends (o, coords));
+	  }
+	}
+	/* update view */
+	diagram_update_connections_selection(DIA_DIAGRAM (data));
+      }
+      g->Release ();
+    }
+  }
+  g_list_free (nodes);
+  g_list_free (edges);
+
+  return changes;
+}
+
+#define AN_ENTRY(name) \
+    { \
+      #name "Layout", \
+      N_(#name), \
+      "/DisplayMenu/Layout/LayoutFirst", \
+      layout_callback, \
+      #name \
+    }
+      
+static DiaCallbackFilter cb_layout[] = {
+    AN_ENTRY(Balloon),
+    AN_ENTRY(Circular),
+    AN_ENTRY(DavidsonHarel),
+    AN_ENTRY(Dominance),
+    //Borked: AN_ENTRY(Fast),
+    AN_ENTRY(FMME),
+    AN_ENTRY(FMMM),
+    AN_ENTRY(GEM),
+    AN_ENTRY(MixedForce),
+    AN_ENTRY(MixedModel),
+    //Borked: AN_ENTRY(Nice),
+    //Borked: AN_ENTRY(NoTwist),
+    AN_ENTRY(Planarization),
+    AN_ENTRY(PlanarDraw),
+    AN_ENTRY(PlanarStraight),
+    AN_ENTRY(PlanarizationGrid),
+    AN_ENTRY(RadialTree),
+    AN_ENTRY(SpringEmbedderFR),
+    AN_ENTRY(SpringEmbedderKK),
+    //Borked: AN_ENTRY(StressMajorization),
+    AN_ENTRY(Sugiyama),
+    AN_ENTRY(Tree),
+    AN_ENTRY(UpwardPlanarization),
+    //Borked: AN_ENTRY(Visibility),
+    AN_ENTRY(NotAvailable),
+    NULL
+};
+
+static gboolean
+_plugin_can_unload (PluginInfo *info)
+{
+  /* there is no filter_unregister_callback yet */
+  return FALSE;
+}
+
+static void
+_plugin_unload (PluginInfo *info)
+{
+  /* todo */
+}
+
+/* --- dia plug-in interface --- */
+extern "C" {
+DIA_PLUGIN_CHECK_INIT
+}
+
+PluginInitResult
+dia_plugin_init(PluginInfo *info)
+{
+  int i = 0;
+
+  if (!dia_plugin_info_init(info, "OGDF Layout",
+                            _("Layout Algorithms"),
+                            _plugin_can_unload,
+                            _plugin_unload))
+    return DIA_PLUGIN_INIT_ERROR;
+
+  while (cb_layout[i].action) {
+#ifdef HAVE_OGDF
+    // no point in adding these without OGDF yet 
+    filter_register_callback (&cb_layout[i]);
+#endif
+    ++i;
+  }
+
+  return DIA_PLUGIN_INIT_OK;
+}
diff --git a/plug-ins/layout/makefile.msc b/plug-ins/layout/makefile.msc
new file mode 100644
index 0000000..1f4317a
--- /dev/null
+++ b/plug-ins/layout/makefile.msc
@@ -0,0 +1,429 @@
+# One to rule all of them - vc version agnostic
+# Not using the OGDF build approach for two reasons
+#  - need a simple wrapper to use in Dia with different C++ runtime
+#  - make it buildable with vc2005 and above
+
+!IFNDEF PACKAGE
+
+SUBS = augmentation basic cluster decomposition energybased external fileformats graphalg \
+	incremental labeling layered lpsolver misclayout orthogonal packing planarity \
+	planarlayout simultaneous tree upward
+
+
+# The main target
+all : sub-all
+
+sub-all: 
+	for %d in ($(SUBS)) do @nmake -nologo -f makefile.msc sub-one THIS=%d
+	@cd energybased\multilevelmixer
+	@nmake -nologo -f ..\..\makefile.msc multilevelmixer.lib PACKAGE=multilevelmixer OBJ_multilevelmixer=1
+	@cd ..\..
+	@nmake -nologo -f makefile.msc PACKAGE=ogdf ogdf.dll
+
+sub-one:
+	@cd $(THIS)
+	@nmake -nologo -f ..\makefile.msc $(THIS).lib PACKAGE=$(THIS) OBJ_$(THIS)=1
+	@cd ..
+
+clean:
+	for %d in ($(SUBS)) do @nmake -nologo -f makefile.msc sub-clean THIS=%d
+	@nmake -nologo -f makefile.msc PACKAGE=ogdf clean	
+
+sub-clean:
+	@cd $(THIS)
+	@nmake -nologo -f ..\makefile.msc PACKAGE=$(THIS) clean
+	@cd ..
+
+!ELSE
+
+# random crashes due to threaded memory access? YES.
+DEFINES = -DOGDF_MEMORY_MALLOC_TS # -DOGDF_DEBUG
+#DEFINES = -DOGDF_DLL -DOGDF_INSTALL
+
+INCLUDES = \
+	-I ..\..\.. \
+	-I ..\.. \
+	-I .. \
+#	-I D:\Devel\wdk7\inc\api\crt\stl60
+
+PKG_CFLAGS = $(DEFINES) $(INCLUDES) /EHsc /nologo
+
+PKG_LINK = \
+	augmentation/augmentation.lib \
+	basic/basic.lib \
+	cluster/cluster.lib \
+	decomposition/decomposition.lib \
+	energybased/energybased.lib \
+	external/external.lib \
+	fileformats/fileformats.lib \
+	graphalg/graphalg.lib \
+	incremental/incremental.lib \
+	labeling/labeling.lib \
+	layered/layered.lib \
+	lpsolver/lpsolver.lib \
+	misclayout/misclayout.lib \
+	orthogonal/orthogonal.lib \
+	packing/packing.lib \
+	planarity/planarity.lib \
+	planarlayout/planarlayout.lib \
+	simultaneous/simultaneous.lib \
+	tree/tree.lib \
+	upward/upward.lib \
+	energybased\multilevelmixer\multilevelmixer.lib
+
+!IFDEF OBJ_augmentation
+OBJECTS = \
+        DfsMakeBiconnected.obj \
+        PlanarAugmentation.obj \
+        PlanarAugmentationFix.obj \
+	
+!ENDIF
+
+!IFDEF OBJ_basic
+OBJECTS = \
+        basic.obj \
+        CliqueFinder.obj \
+        CombinatorialEmbedding.obj \
+        DualGraph.obj \
+        EdgeComparer.obj \
+        EdgeComparerSimple.obj \
+        extended_graph_alg.obj \
+        geometry.obj \
+        Graph.obj \
+        GraphAttributes.obj \
+        GraphCopy.obj \
+        graph_generators.obj \
+        GridLayout.obj \
+        GridLayoutModule.obj \
+        Hashing.obj \
+        Logger.obj \
+        modules.obj \
+        NearestRectangleFinder.obj \
+        PoolMemoryAllocator.obj \
+        PreprocessorLayout.obj \
+        random_hierarchy.obj \
+        simple_graph_alg.obj \
+        stNumber.obj \
+        String.obj \
+        System.obj \
+        UMLGraph.obj \
+
+!ENDIF
+
+!IFDEF OBJ_cluster
+OBJECTS = \
+        CconnectClusterPlanar.obj \
+        CconnectClusterPlanarEmbed.obj \
+        Clusterer.obj \
+        ClusterGraph.obj \
+        ClusterGraphAttributes.obj \
+        ClusterPlanarizationLayout.obj \
+        Cluster_ChunkConnection.obj \
+        Cluster_CutConstraint.obj \
+        Cluster_EdgeVar.obj \
+        Cluster_MaxPlanarEdges.obj \
+        CPlanarEdgeInserter.obj \
+        CPlanarSubClusteredGraph.obj \
+        CPlanarSubCLusteredST.obj \
+        KuratowskiConstraint.obj \
+        MaxCPlanar_Master.obj \
+        MaxCPlanar_MinimalClusterConnection.obj \
+        MaxCPlanar_Sub.obj \
+        MaximumCPlanarSubgraph.obj \
+
+!ENDIF
+
+!IFDEF OBJ_decomposition 
+OBJECTS = \
+        BCTree.obj \
+        DynamicBCTree.obj \
+        DynamicSPQRForest.obj \
+        DynamicSPQRTree.obj \
+        NonPlanarCore.obj \
+        PlanarSPQRTree.obj \
+        StaticSPQRTree.obj \
+        TricComp.obj \
+
+!ENDIF
+
+!IFDEF OBJ_external 
+OBJECTS = \
+	coin.obj
+!ENDIF
+
+!IFDEF OBJ_energybased 
+OBJECTS = \
+        AdjacencyOracle.obj \
+        ArrayGraph.obj \
+        Attraction.obj \
+        CoinTutteLayout.obj \
+        DavidsonHarel.obj \
+        DavidsonHarelLayout.obj \
+        EdgeAttributes.obj \
+        EnergyFunction.obj \
+        FastMultipoleEmbedder.obj \
+        FastUtils.obj \
+        FMEKernel.obj \
+        FMEMultipoleKernel.obj \
+        FMEThread.obj \
+        FMMMLayout.obj \
+        FruchtermanReingold.obj \
+        GalaxyMultilevel.obj \
+        GEMLayout.obj \
+        IntersectionRectangle.obj \
+        LinearQuadtree.obj \
+        LinearQuadtreeBuilder.obj \
+        LinearQuadtreeExpansion.obj \
+        MAARPacking.obj \
+        Multilevel.obj \
+        MultilevelGraph.obj \
+        NMM.obj \
+        NodeAttributes.obj \
+        NodePairEnergy.obj \
+        numexcept.obj \
+        Overlap.obj \
+        Planarity.obj \
+        PlanarityGrid.obj \
+        QuadTreeNM.obj \
+        QuadTreeNodeNM.obj \
+        Repulsion.obj \
+        Set.obj \
+        SpringEmbedderFR.obj \
+        SpringEmbedderFRExact.obj \
+        SpringEmbedderKK.obj \
+        StressMajorizationSimple.obj \
+        UniformGrid.obj \
+        WSPD.obj \
+
+!ENDIF
+
+!IFDEF OBJ_fileformats
+OBJECTS = \
+        DinoLineBuffer.obj \
+        DinoTools.obj \
+        DinoUmlDiagramGraph.obj \
+        DinoUmlModelGraph.obj \
+        DinoUmlToGraphConverter.obj \
+        DinoXmlParser.obj \
+        DinoXmlScanner.obj \
+        GmlParser.obj \
+        OgmlParser.obj \
+        simple_graph_load.obj \
+        XmlParser.obj \
+
+!ENDIF
+
+!IFDEF OBJ_graphalg
+OBJECTS = \
+        ConvexHull.obj \
+        mcf_front_reinelt.obj \
+        MinCostFlowModule.obj \
+        MinCostFlowReinelt.obj \
+        MinimumCut.obj \
+        ShortestPathsWithBFM.obj \
+
+!ENDIF
+
+!IFDEF OBJ_incremental 
+OBJECTS = \
+        SimpleIncNodeInserter.obj \
+
+!ENDIF
+
+!IFDEF OBJ_labeling 
+OBJECTS = \
+        ELabelPosSimple.obj \
+
+!ENDIF
+
+!IFDEF OBJ_layered 
+OBJECTS = \
+        acyclic_subgraph.obj \
+        CrossingsMatrix.obj \
+        FastHierarchyLayout.obj \
+        heuristics.obj \
+        HierarchyLayoutModule.obj \
+        OptimalHierarchyClusterLayout.obj \
+        OptimalHierarchyLayout.obj \
+        OptimalRanking.obj \
+        ranking.obj \
+        SplitHeuristic.obj \
+        sugiyama-cluster.obj \
+        sugiyama.obj \
+
+!ENDIF
+
+!IFDEF OBJ_lpsolver 
+OBJECTS = \
+        LPSolver_coin.obj \
+
+!ENDIF
+
+!IFDEF OBJ_misclayout 
+OBJECTS = \
+        BalloonLayout.obj \
+        CircularLayout.obj \
+
+!ENDIF
+
+!IFDEF OBJ_orthogonal 
+OBJECTS = \
+        ClusterOrthoLayout.obj \
+        ClusterOrthoShaper.obj \
+        CompactionConstraintGraph.obj \
+        EdgeRouter.obj \
+        FlowCompaction.obj \
+        LongestPathCompaction.obj \
+        NodeInfo.obj \
+        OrthoLayout.obj \
+        OrthoRep.obj \
+        OrthoShaper.obj \
+
+!ENDIF
+
+!IFDEF OBJ_packing 
+OBJECTS = \
+        CCLayoutPackModule.obj \
+        ComponentSplitterLayout.obj \
+        TileToRowsCCPacker.obj \
+
+!ENDIF
+
+!IFDEF OBJ_planarity
+OBJECTS = \
+        BoyerMyrvold.obj \
+        BoyerMyrvoldInit.obj \
+        BoyerMyrvoldPlanar.obj \
+        ClusterPlanRep.obj \
+        EdgeInsertionModule.obj \
+        EmbedderMaxFace.obj \
+        EmbedderMaxFaceLayers.obj \
+        EmbedderMDMFLengthAttribute.obj \
+        EmbedderMinDepth.obj \
+        EmbedderMinDepthMaxFace.obj \
+        EmbedderMinDepthMaxFaceLayers.obj \
+        EmbedderMinDepthPiTa.obj \
+        EmbedPQTree.obj \
+        ExtractKuratowskis.obj \
+        FastPlanarSubgraph.obj \
+        FindKuratowskis.obj \
+        FixedEmbeddingInserter.obj \
+        GraphReduction.obj \
+        Layout.obj \
+        LayoutPlanRepModule.obj \
+        MaximalPlanarSubgraphSimple.obj \
+        MaximumPlanarSubgraph.obj \
+        MMCrossingMinimizationModule.obj \
+        MMFixedEmbeddingInserter.obj \
+        MMSubgraphPlanarizer.obj \
+        MMVariableEmbeddingInserter.obj \
+        PlanarizationGridLayout.obj \
+        PlanarizationLayout.obj \
+        PlanarizationLayout_inc.obj \
+        PlanarModule.obj \
+        PlanarPQTree.obj \
+        PlanarSubgraphModule.obj \
+        PlanarSubgraphPQTree.obj \
+        PlanRep.obj \
+        PlanRepExpansion.obj \
+        PlanRepInc.obj \
+        PlanRepUML.obj \
+        SimpleEmbedder.obj \
+        SubgraphPlanarizer.obj \
+        TopologyModule.obj \
+        VariableEmbeddingInserter.obj \
+        VariableEmbeddingInserter2.obj \
+
+!ENDIF
+
+!IFDEF OBJ_planarlayout 
+OBJECTS = \
+        BiconnectedShellingOrder.obj \
+        IOPoints.obj \
+        MixedModelBase.obj \
+        MixedModelCrossingsBeautifierModule.obj \
+        MixedModelLayout.obj \
+        MMCBBase.obj \
+        PlanarDrawLayout.obj \
+        PlanarStraightLayout.obj \
+        ShellingOrder.obj \
+        ShellingOrderModule.obj \
+        TriconnectedShellingOrder.obj \
+
+!ENDIF
+
+!IFDEF OBJ_simultaneous 
+OBJECTS = \
+        SimDraw.obj \
+        SimDrawCaller.obj \
+        SimDrawColorizer.obj \
+        SimDrawCreator.obj \
+        SimDrawCreatorSimple.obj \
+        SimDrawManipulatorModule.obj \
+
+!ENDIF
+
+!IFDEF OBJ_tree 
+OBJECTS = \
+        RadialTreeLayout.obj \
+        TreeLayout.obj \
+
+!ENDIF
+
+!IFDEF OBJ_upward
+OBJECTS = \
+        DominanceLayout.obj \
+        ExpansionGraph.obj \
+        FaceSinkGraph.obj \
+        FeasibleUpwardPlanarSubgraph.obj \
+        FixedEmbeddingUpwardEdgeInserter.obj \
+        FUPSSimple.obj \
+        LayerBasedUPRLayout.obj \
+        SubgraphUpwardPlanarizer.obj \
+        UpwardPlanarModule.obj \
+        UpwardPlanarSubgraphModule.obj \
+        UpwardPlanarSubgraphSimple.obj \
+        UpwardPlanRep.obj \
+        VisibilityLayout.obj \
+
+!ENDIF
+
+!IFDEF OBJ_multilevelmixer
+OBJECTS = \
+        BarycenterPlacer.obj \
+        CirclePlacer.obj \
+        EdgeCoverMerger.obj \
+        IndependentSetMerger.obj \
+        LocalBiconnectedMerger.obj \
+        MatchingMerger.obj \
+        MedianPlacer.obj \
+        MixedForceLayout.obj \
+        MMMExampleFastLayout.obj \
+        MMMExampleNiceLayout.obj \
+        MMMExampleNoTwistLayout.obj \
+        ModularMultilevelMixerLayout.obj \
+        RandomMerger.obj \
+        RandomPlacer.obj \
+        ScalingLayout.obj \
+        SolarMerger.obj \
+        SolarPlacer.obj \
+        ZeroPlacer.obj \
+
+!ENDIF
+
+$(PACKAGE).lib : $(OBJECTS)
+	lib /out:$(PACKAGE).lib $(OBJECTS)
+
+# /link /MAP:ogdf.map /machine:ix86 /OPT:REF
+$(PACKAGE).dll : ogdf-simple.obj $(PKG_LINK)
+	$(CC) $(CFLAGS) -Zi -LD -Fe$(PACKAGE).dll ogdf-simple.obj \
+	$(PKG_LINK) $(EXTRALIBS) user32.lib kernel32.lib psapi.lib $(LDFLAGS) /link /MAP:ogdf.map 
+
+.cpp.obj :
+	$(CC) -Zi -MT $(CFLAGS) -c $(PKG_CFLAGS) $<
+
+
+clean:
+	del *.obj *.pdb *.ilk *.lib *.dll *.map
+
+!ENDIF
diff --git a/plug-ins/layout/ogdf-simple.cpp b/plug-ins/layout/ogdf-simple.cpp
new file mode 100644
index 0000000..1f61651
--- /dev/null
+++ b/plug-ins/layout/ogdf-simple.cpp
@@ -0,0 +1,380 @@
+/* Simple wrapper around OGDF 
+ * - making a weaker dependency, especially for memory management
+ * - also designed for Dia's need to simply try out some layout algorithms
+ * - might even become a C or D interface to OGDF?
+ *
+ * Author:
+ *   Hans Breuer <hans breuer org>
+ *
+ * This code is in public domain
+ */
+
+#include <ogdf/energybased/GEMLayout.h>
+#include <ogdf/energybased/FMMMLayout.h>
+#include <ogdf/energybased/FastMultipoleEmbedder.h>
+#include <ogdf/misclayout/BalloonLayout.h>
+#include <ogdf/misclayout/CircularLayout.h>
+#include <ogdf/energybased/DavidsonHarelLayout.h>
+#include <ogdf/energybased/StressMajorizationSimple.h>
+#include <ogdf/layered/SugiyamaLayout.h>
+#include <ogdf/layered/OptimalHierarchyLayout.h>
+#include <ogdf/upward/DominanceLayout.h>
+#include <ogdf/upward/UpwardPlanarizationLayout.h>
+#include <ogdf/upward/VisibilityLayout.h>
+#include <ogdf/energybased/SpringEmbedderFR.h>
+#include <ogdf/energybased/SpringEmbedderKK.h>
+#include <ogdf/tree/TreeLayout.h>
+#include <ogdf/tree/RadialTreeLayout.h>
+#include <ogdf/planarlayout/MixedModelLayout.h>
+#include <ogdf/planarlayout/PlanarDrawLayout.h>
+#include <ogdf/planarlayout/PlanarStraightLayout.h>
+#include <ogdf/planarity/PlanarizationLayout.h>
+#include <ogdf/planarity/PlanarizationGridLayout.h>
+
+#include <ogdf/energybased/multilevelmixer/MMMExampleFastLayout.h>
+#include <ogdf/energybased/multilevelmixer/MMMExampleNiceLayout.h>
+#include <ogdf/energybased/multilevelmixer/MMMExampleNoTwistLayout.h>
+#include <ogdf/energybased/multilevelmixer/MixedForceLayout.h>
+
+#include <ogdf/orthogonal/OrthoLayout.h>
+
+#define DLL_EXPORT __declspec(dllexport)
+#include "ogdf-simple.h"
+
+namespace {
+
+class KGraph : public IGraph
+{
+    //! mapping indices to node pointers
+    std::vector<ogdf::node> m_nodes;
+    //! averege node size updated during graph constructions
+    double m_avgNodeSize;
+    // mapping edges
+    std::vector<ogdf::edge> m_edges;
+    //! average edge length (direct line) updated during graph constructions
+    double m_avgEdgeLen;
+    //! the basic graph
+    ogdf::Graph *m_pGraph;
+    //! including the geometric information 
+    ogdf::GraphAttributes *m_pGraphAttrs;
+    //! valid after Layout method call
+    ogdf::LayoutModule *m_pLayout;
+
+    //! use IGrap:Release()
+    ~KGraph ();
+    
+    //! just scale by 
+    static const int m_scale = 20;
+public :
+    //! Clean up and destroy the graph
+    void Release ();
+    //! Create a new node with bounding box and return it's index
+    int AddNode (double left, double top, double right, double bottom);
+    //! Create a new edge and return it's index
+    int AddEdge (int srcNode, int destNode, double* points, int len);
+
+    //! layout the graph
+    eResult Layout (const char *module);
+
+    // Layout result left,top
+    bool GetNodePosition (int node, double* x, double* y);
+    int  GetEdgeBends (int e, double *coords, int len);
+
+    //! only internally used by factory function
+    KGraph ();
+protected :
+    //! internal layout function w/o exception handler
+    bool RealLayout (const char *module);
+};
+
+KGraph::KGraph() :
+    m_pGraph(new ogdf::Graph()),
+    m_pGraphAttrs(new ogdf::GraphAttributes(*m_pGraph, 
+					    ogdf::GraphAttributes::nodeGraphics 
+					    | ogdf::GraphAttributes::edgeGraphics
+					    | ogdf::GraphAttributes::edgeType)),
+    m_pLayout(NULL),
+    m_avgNodeSize(0),
+    m_avgEdgeLen(0)
+{
+}
+KGraph::~KGraph()
+{
+    if (m_pGraphAttrs)
+        delete m_pGraphAttrs;
+    if (m_pGraph)
+        delete m_pGraph;
+    if (m_pLayout)
+        delete m_pLayout;
+}
+void
+KGraph::Release ()
+{
+    delete this;
+}
+
+int 
+KGraph::AddNode (double left, double top, double right, double bottom)
+{
+    ogdf::node node = m_pGraph->newNode();
+    double w = (right - left);
+    double h = (bottom - top);
+
+    // apparently we have to give the center of the node
+    m_pGraphAttrs->x(node) = (left + w/2) * m_scale;
+    m_pGraphAttrs->y(node) = (top + h/2) * m_scale;
+    m_pGraphAttrs->width(node) = w * m_scale;
+    m_pGraphAttrs->height(node) = h * m_scale;
+
+    m_avgNodeSize = ((m_avgNodeSize * m_nodes.size()) + (w * m_scale) * (h * m_scale)) / (m_nodes.size() + 1);
+    m_nodes.push_back (node);
+
+    return m_nodes.size();
+}
+
+int 
+KGraph::AddEdge (int srcNode, int dstNode, double* coords, int len)
+{
+    ogdf::edge edge;
+    ogdf::node src;
+    ogdf::node dst;
+  
+    if (srcNode < 0 || srcNode >= m_nodes.size())
+	return -1;
+    if (dstNode < 0 || dstNode >= m_nodes.size())
+	return -2;
+
+    src = m_nodes[srcNode];
+    dst = m_nodes[dstNode];
+    double xs, xd, ys, yd;
+    GetNodePosition (srcNode, &xs, &ys);
+    GetNodePosition (srcNode, &xd, &yd);
+    double dist = sqrt((xd - xs) * (xd - xs) + (yd - ys) * (yd - ys)) * m_scale;
+
+    edge = m_pGraph->newEdge(src, dst);
+
+    // initialization of points
+    if (len > 0)
+    {
+	ogdf::DPolyline &poly = m_pGraphAttrs->bends(edge);
+	for (int i = 0; i < len; i+=2)
+	     poly.pushBack (ogdf::DPoint (coords[i] * m_scale, coords[i+1] * m_scale));
+    }
+    m_avgEdgeLen = (m_avgEdgeLen * m_edges.size() + dist) / (m_edges.size() + 1);
+    m_edges.push_back (edge);
+
+    return m_edges.size();
+}
+
+bool
+KGraph::RealLayout (const char *module)
+{
+    // improve default initialization - distance from node size
+    const double distFactor = 1.5;
+#ifdef OGDF_DEBUG
+    m_pGraphAttrs->writeGML ("d:\\temp\\ogdf-simple-pre.gml");
+#endif
+    if (strcmp ("Balloon", module) == 0)
+        m_pLayout = new ogdf::BalloonLayout ();
+    else if (strcmp ("Circular", module) == 0)
+        m_pLayout = new ogdf::CircularLayout ();
+    else if (strcmp ("DavidsonHarel", module) == 0)
+    {
+        ogdf::DavidsonHarelLayout *pLayout = new ogdf::DavidsonHarelLayout ();
+        pLayout->setPreferredEdgeLength (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("Dominance", module) == 0)
+    {
+        ogdf::DominanceLayout *pLayout = new ogdf::DominanceLayout ();
+	pLayout->setMinGridDistance (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("FMMM", module) == 0)
+    {
+        ogdf::FMMMLayout *pLayout = new ogdf::FMMMLayout ();
+        pLayout->unitEdgeLength (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("FMME", module) == 0)
+        m_pLayout = new ogdf::FastMultipoleMultilevelEmbedder ();
+    else if (strcmp ("GEM", module) == 0)
+    {
+        ogdf::GEMLayout *pLayout = new ogdf::GEMLayout ();
+        pLayout->minDistCC (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;new ogdf::GEMLayout ();
+    }
+    else if (strcmp ("MixedForce", module) == 0)
+        m_pLayout = new ogdf::MixedForceLayout ();
+    else if (strcmp ("MixedModel", module) == 0)
+        m_pLayout = new ogdf::MixedModelLayout();
+    else if (strcmp ("Nice", module) == 0)
+        m_pLayout = new ogdf::MMMExampleNiceLayout ();
+    else if (strcmp ("Fast", module) == 0)
+	m_pLayout = new ogdf::MMMExampleFastLayout();
+    else if (strcmp ("NoTwist", module) == 0)
+	m_pLayout = new ogdf::MMMExampleNoTwistLayout();
+    else if (strcmp ("Planarization", module) == 0)
+        m_pLayout = new ogdf::PlanarizationLayout ();
+    else if (strcmp ("PlanarDraw", module) == 0)
+	m_pLayout = new ogdf::PlanarDrawLayout();
+    else if (strcmp ("PlanarStraight", module) == 0)
+	m_pLayout = new ogdf::PlanarStraightLayout();
+    else if (strcmp ("PlanarizationGrid", module) == 0)
+	m_pLayout = new ogdf::PlanarizationGridLayout();
+    else if (strcmp ("RadialTree", module) == 0)
+        m_pLayout = new ogdf::RadialTreeLayout ();
+    else if (strcmp ("SpringEmbedderFR", module) == 0)
+    {
+        ogdf::SpringEmbedderFR *pLayout = new ogdf::SpringEmbedderFR ();
+        pLayout->minDistCC (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("SpringEmbedderKK", module) == 0)
+    {
+        ogdf::SpringEmbedderKK *pLayout = new ogdf::SpringEmbedderKK ();
+	pLayout->setDesLength (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("StressMajorization", module) == 0)
+    {
+        ogdf::StressMajorization *pLayout = new ogdf::StressMajorization ();
+	//private: pLayout->desMinLength (std::max(m_avgEdgeLen, sqrt(m_avgNodeSize)*distFactor));
+	pLayout->setUseLayout (true);
+        m_pLayout = pLayout;
+    }
+    else if (strcmp ("Sugiyama", module) == 0)
+    {
+        ogdf::SugiyamaLayout *pLayout = new ogdf::SugiyamaLayout ();
+        pLayout->setRanking (new ogdf::OptimalRanking ());
+        m_pLayout = new ogdf::SugiyamaLayout ();
+    }
+    else if (strcmp ("Tree", module) == 0)
+        m_pLayout = new ogdf::TreeLayout ();
+    else if (strcmp ("UpwardPlanarization", module) == 0)
+        m_pLayout = new ogdf::UpwardPlanarizationLayout ();
+    else if (strcmp ("Visibility", module) == 0)
+        m_pLayout = new ogdf::VisibilityLayout ();
+    else
+        m_pLayout = NULL;
+
+    if (!m_pLayout)
+        return false;
+
+    m_pLayout->call (*m_pGraphAttrs);
+    m_pGraphAttrs->removeUnnecessaryBendsHV ();
+#ifdef OGDF_DEBUG
+    //FIXME: debugging
+    m_pGraphAttrs->writeGML ("d:\\temp\\ogdf-simple-post.gml");
+#endif
+    return true;
+}
+
+//! API function which should filter all exceptions
+IGraph::eResult
+KGraph::Layout (const char *module)
+{
+    try
+    {
+	if (RealLayout (module))
+	    return SUCCESS;
+	else
+	    return NO_MODULE;
+    }
+    catch (ogdf::InsufficientMemoryException &e)
+    {
+	return OUT_OF_MEMORY;
+    }
+    catch (ogdf::PreconditionViolatedException &e)
+    {
+        fprintf (stderr, "odgf:Precontion %d failed", e.exceptionCode());
+	switch (e.exceptionCode())
+	{
+	case ogdf::pvcTree : return NO_TREE;
+	case ogdf::pvcForest : return NO_FOREST;
+	default : return  FAILED_PRECONDITION;
+	}
+    }
+    catch (ogdf::AlgorithmFailureException &e)
+    {
+        fprintf (stderr, "odgf:Algorithm %d failed", e.exceptionCode());
+        return FAILED_ALGORITHM;
+    }
+    catch (ogdf::Exception& e)
+    {
+	if (e.file())
+	    fprintf (stderr, "odgf:Exception: %s:%d\n", e.file(), e.line());
+	return FAILED;
+    }
+    catch (std::bad_alloc &e)
+    {
+	fprintf (stderr, "Out of memory: %s\n", e.what());
+	return OUT_OF_MEMORY;
+    }
+    catch (std::exception &e)
+    {
+	fprintf (stderr, "Failed: %s\n", e.what());
+	return FAILED;
+    }
+    catch (...)
+    {
+	return CRASHED;
+    }
+}
+
+bool
+KGraph::GetNodePosition (int n, double* x, double* y)
+{
+    if (!m_pLayout)
+        return false;
+    
+    if (n < 0 || n >= m_nodes.size())
+        return false;
+
+    ogdf::node node = m_nodes[n];
+    
+    if (x)
+        *x = (m_pGraphAttrs->x(node) - m_pGraphAttrs->width(node)/2) / m_scale;
+    if (y)
+        *y = (m_pGraphAttrs->y(node) - m_pGraphAttrs->height(node)/2) / m_scale;
+
+    return true;
+}
+
+int
+KGraph::GetEdgeBends (int e, double *coords, int len)
+{
+    if (!m_pLayout)
+        return 0;
+    
+    if (e < 0 || e >= m_edges.size())
+        return 0;
+
+    ogdf::edge edge = m_edges[e];
+    const ogdf::DPolyline& poly = m_pGraphAttrs->bends(edge);
+
+    if (!coords || len <= 0)
+        return  poly.size() * 2;
+
+    for (int i = 0; i < poly.size()*2 && (i <len); i+=2)
+    {
+        ogdf::ListConstIterator<ogdf::DPoint> it = poly.get(i/2);
+        coords[i  ] = (*it).m_x / m_scale;
+	coords[i+1] = (*it).m_y / m_scale;
+    }
+    
+    return poly.size() * 2;
+}
+
+} // namespace
+
+/*!
+ * Factory function to construct a graph
+ */
+DLL_EXPORT IGraph *
+CreateGraph ()
+{
+    IGraph *pg = new KGraph();
+    
+    return pg;
+}
diff --git a/plug-ins/layout/ogdf-simple.h b/plug-ins/layout/ogdf-simple.h
new file mode 100644
index 0000000..0b4f184
--- /dev/null
+++ b/plug-ins/layout/ogdf-simple.h
@@ -0,0 +1,71 @@
+/*!
+ * A very simple inteface to use graph layout algorithms with Dia
+ *
+ * For OGDF ( http://www.ogdf.net ) main problem to solve is the 
+ * compiler mismatch on Windows.
+ * Dia (and GTK+) are still bound to use vc6, but that's not enough 
+ * C++ to compile OGDF.
+ *
+ * But this is so simple that it should be possible to wrap other graph
+ * layout libraries with the same interface, too.
+ *
+ * Author:
+ *   Hans Breuer <hans breuer org>
+ *
+ * This code is in public domain
+ */
+#ifndef OGDF_SIMPLE_H
+#define OGDF_SIMPLE_H
+
+#ifndef DLL_EXPORT 
+#define DLL_EXPORT 
+#endif
+
+/*!
+ * \brief Abstract graph interface to be fed by Dia
+ *
+ * This interface must not expose any allocation/deallocations and it shall
+ * not let pass any exceptions, because the consumer probaly can't catch them. 
+ */
+class IGraph
+{
+public :
+    //! Clean up and destroy the graph
+    virtual void Release () = 0;
+    //! Create a new node with bounding box and return it's index
+    virtual int AddNode (double left, double top, double right, double bottom) = 0;
+    //! Create a new edge and return it's index
+    virtual int AddEdge (int srcNode, int destNode, double* points, int len) = 0;
+
+    //! some hints what was going wrong
+    typedef enum {
+	SUCCESS = 0,
+	NO_MODULE,
+	OUT_OF_MEMORY,
+	NO_TREE,
+	NO_FOREST,
+	FAILED_PRECONDITION,
+	FAILED_ALGORITHM,
+	FAILED,
+	CRASHED // catch (...)
+    } eResult;
+    //! layout the graph
+    virtual eResult Layout (const char *module) = 0;
+
+    // Layout result left,top
+    virtual bool GetNodePosition (int node, double* x, double* y) = 0;
+    // Layout result bends - fill sized array of coords
+    virtual int GetEdgeBends (int e, double *coords, int len) = 0;
+protected :
+    //! use factory function
+    IGraph () {}
+    //! use Release() instead
+    ~IGraph () {}
+private :
+    //! no copy construction
+    IGraph (const IGraph&);
+};
+
+DLL_EXPORT IGraph *CreateGraph ();
+
+#endif
diff --git a/plug-ins/layout/readme.txt b/plug-ins/layout/readme.txt
new file mode 100644
index 0000000..2a9e77e
--- /dev/null
+++ b/plug-ins/layout/readme.txt
@@ -0,0 +1,41 @@
+A Dia plug-in offering automatic layout facilities
+--------------------------------------------------
+
+This plug-on is based on OGDF (www.ogdf.net).
+"OGDF is a self-contained C++ class library for the automatic layout of diagrams."
+
+The plug-in uses a self-devolved wrapper over OGDF (ogdf-simple(h|cpp)), mostly to 
+allow a special build setup on win32. But IMO the plug-in also benefits of depending
+on a much smaller API. This way it should be easy to plug in other layout libraries
+without too much trouble.
+
+Build without OGDF
+------------------
+Don't define HAVE_OGDF and layout.cpp gets compiled without OGDF dependency.
+This does not give any of the automatic layout facility, but should be useful
+to keep the plug-in buildable when Dia specifics change.
+
+Build setup on win32
+--------------------
+Dia's standard compiler on win32 is vc6, which does not support enough C++ to compile OGDF.
+There is not only the problem of compile time, but also at runtime there should not be two
+C++ runtimes in one process. And of course we should spare the burden of msvcrXX.dll 
+distribution.
+The header ogdf-simple.h defines a C++ version agnostic interface (no exceptions, no 
+allocation details accross DLL boundaries) which makes OGDF build by any VC++ compiler
+useable in the context of Dia.
+Simply copy ogdf-simple.(h|cpp) and makefile.msc into the OGDF/src directory and call
+	nmake -f makefile.msc
+After building OGDF.dll configure your build setup in $(TOP)\glib\build\win32\make.msc to 
+define include path and library linkage, mine has:
+
+OGDF_CFLAGS = -I $(TOP)\..\other\ogdf\src -DHAVE_OGDF
+OGDF_LIBS = $(TOP)\..\other\ogdf\src\ogdf.lib
+	
+
+Build on *NIX
+-------------
+Makefile.am
+HAVE_OGDF
+OGDF_CFLAGS
+OGDF_LIBS
diff --git a/plug-ins/makefile.msc b/plug-ins/makefile.msc
index 89eaa50..6854fae 100644
--- a/plug-ins/makefile.msc
+++ b/plug-ins/makefile.msc
@@ -3,7 +3,7 @@
 # dummy sissi
 PLUGINS = cairo cgm dxf hpgl libart metapost pgf pixbuf \
 	postscript pstricks shape svg vdx wmf wpg xfig xslt \
-	drs stress
+	drs stress layout
 
 # The main target
 all : sub-all
@@ -85,6 +85,13 @@ OBJECTS = \
   dxf-import.obj
 !ENDIF
 
+!IFDEF OBJ_layout
+DEPCFLAGS = -GX -I $(PRJ_TOP)\app $(OGDF_CFLAGS)
+PKG_LINK = $(PKG_LINK) $(PRJ_TOP)\app\dia-app.lib $(OGDF_LIBS)
+OBJECTS = \
+	layout.obj
+!ENDIF
+
 !IFDEF OBJ_libart
 DEPCFLAGS = -DHAVE_LIBART -DHAVE_LIBPNG $(LIBART_CFLAGS) $(PNG_CFLAGS)
 PKG_LINK = $(PKG_LINK) $(LIBART_LIBS) $(PNG_LIBS) ..\..\app\dia-app.lib



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]