[dia] OGDF based automatic layout plug-in for Dia
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] OGDF based automatic layout plug-in for Dia
- Date: Mon, 3 Oct 2011 15:11:53 +0000 (UTC)
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]