/// <summary>Creates a new <see cref=""/> instance.</summary> public DiagramPaginator(DiagramCanvas source, Size printSize) { PageSize = printSize; _contentSize = new Size(printSize.Width - 2 * Margin, printSize.Height - 2 * Margin); _frameRect = new Rect(new Point(Margin, Margin), _contentSize); _frameRect.Inflate(1, 1); _framePen = new Pen(Brushes.Black, 0.1); var scale = 0.25; // hardcoded zoom for printing var bounds = new Rect(0, 0, source.ActualWidth, source.ActualHeight); _pageCountX = (int)((bounds.Width * scale) / _contentSize.Width) + 1; _pageCountY = (int)((bounds.Height * scale) / _contentSize.Height) + 1; // Transformation to borderless print size var matrix = new Matrix(); matrix.Translate(-bounds.Left, -bounds.Top); matrix.Scale(scale, scale); matrix.Translate((_pageCountX * _contentSize.Width - bounds.Width * scale) / 2, (_pageCountY * _contentSize.Height - bounds.Height * scale) / 2); // Create a new visual var printImage = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32); printImage.Render(source); var printVisual = new DrawingVisual(); var printContext = printVisual.RenderOpen(); printContext.PushTransform(new MatrixTransform(matrix)); printContext.DrawImage(printImage, bounds); printContext.Close(); _printDiagram = printVisual.Drawing; }
/// <summary>Computes the layout of the given diagram.</summary> public static void ComputeLayout(DiagramCanvas diagram, List<DiagramEdgeInfo> edgeList, bool isClustered) { try { _computeLayout(diagram, edgeList, isClustered, false); } catch { // try again with less constraints _computeLayout(diagram, edgeList, isClustered, true); } }
// Invoked to initially draw the edge internal void Draw(DiagramCanvas diagram) { diagram.EdgesLayer.Children.Add(this); LayoutChanged(); }
/// <summary>Creates a new <see cref="DiagramSprite"/> instance.</summary> public DiagramSprite(DiagramCanvas canvas, long id) { Canvas = canvas; Id = id; Visibility = ComputedVisibility = Visibility.Hidden; }
private static void _computeLayout(DiagramCanvas diagram, List<DiagramEdgeInfo> edgeList, bool isClustered, bool safeMode) { var graphFile = Path.GetTempFileName(); var layoutFile = Path.GetTempFileName(); Func<DisplayOptions, bool> hasOption = option => diagram.DisplayOptions.Has(option); // create the input graph using (var fs = File.CreateText(graphFile)) { var gparams = new List<string>(); gparams.Add("overlap=compress"); gparams.Add("pack=true"); if (diagram.LayoutRatio == LayoutRatio.Fill && diagram.AspectRatio.IsPositive()) { gparams.Add("ratio=" + diagram.AspectRatio); } else { gparams.Add("ratio=compress"); } if (!safeMode) { gparams.Add("sep=0.2"); gparams.Add("ranksep=1.0"); if (hasOption(DisplayOptions.ShowAssociations) || hasOption(DisplayOptions.ShowContainment) || hasOption(DisplayOptions.ShowCollaborations)) { gparams.Add("nodesep=1.5"); } else { gparams.Add("nodesep=0.75"); } } switch (diagram.LayoutOrientation) { case LayoutOrientation.TopToBottom: gparams.Add("rankdir=TB"); break; case LayoutOrientation.LeftToRight: gparams.Add("rankdir=LR"); break; case LayoutOrientation.BottomToTop: gparams.Add("rankdir=BT"); break; case LayoutOrientation.RightToLeft: gparams.Add("rankdir=RL"); break; } fs.WriteLine("digraph BPL { "); fs.WriteLine("\tgraph [" + gparams.ToArray().Join(", ") + "]; "); var visibleNodes = diagram.Nodes.Where(n => _isVisible(n)); Func<DiagramNode, string> nodeAttrs = node => "{0} [width={1},height={2},shape=box];".Substitute(node.Id, node.ComputedSize.Width / 72, node.ComputedSize.Height / 72); if (isClustered) { var clusterNo = 0; foreach (var ns in visibleNodes.GroupBy(n => n.Class.Namespace)) { fs.WriteLine("\tsubgraph cluster" + (clusterNo++) + " {"); fs.WriteLine("\t\tgraph[label=\"{0}\"]".Substitute(ns.Key.Name)); foreach (var node in ns) { fs.WriteLine("\t\t" + nodeAttrs(node)); } fs.WriteLine("\t}"); } } else { foreach (var node in visibleNodes) { fs.WriteLine("\t" + nodeAttrs(node)); } } foreach (var edge in edgeList) { var edgeId = "{0} -> {1}".Substitute(edge.Source.Id, edge.Target.Id); var arrows = String.Empty; arrows += _hasRole(edge, DiagramEdgeRole.Inheritance | DiagramEdgeRole.Containment) ? "arrowtail=normal, " : "arrowtail=none, "; arrows += _hasRole(edge, DiagramEdgeRole.Containment | DiagramEdgeRole.Association | DiagramEdgeRole.WeakAssociation) ? "arrowhead=normal, " : "arrowhead=none, "; fs.WriteLine("\t{0} [{1}label=\"{2}\", color=\"0x{3:X6}\"];".Substitute(edgeId, arrows, edge.Label, (int)edge.Role)); } fs.WriteLine("}"); } // unflatten the input graph if (diagram.LayoutMethod == LayoutMethod.Hierarchic) { var tempFile = graphFile; _invokeLayoutEngine("unflatten", "-l7 -f -c7 -o \"{0}\" \"{1}\"".Substitute(layoutFile, graphFile)); graphFile = layoutFile; layoutFile = tempFile; } // compute the graph layout var engineName = _layoutEngineNames[(int)diagram.LayoutMethod]; _invokeLayoutEngine(engineName, "-Tdot -o \"{0}\" \"{1}\"".Substitute(layoutFile, graphFile)); // parse the computed graph size DotParser.Parse(layoutFile, diagram); // remove temporary files File.Delete(graphFile); File.Delete(layoutFile); }
public static void Parse(string path, DiagramCanvas diagram) { var parser = new PlainParser(path); if (parser.ReadLine("graph")) { parser.NextToken(); var size = parser.NextSize(); diagram.ComputedSize = size; diagram.Width = size.Width; diagram.Height = size.Height; parser._coordTransform = (x, y) => new Point(x, size.Height - y); } // parse the computed node positions while (parser.ReadLine("node")) { var node = diagram.Nodes[parser.NextInt()]; node.ComputedPosition = parser.NextPoint(); } // parse the computed edge paths while (parser.ReadLine("edge")) { var source = diagram.Nodes[parser.NextInt()]; var target = diagram.Nodes[parser.NextInt()]; var points = new PointCollection(); for (var n = parser.NextInt(); n > 0; n--) { points.Add(parser.NextPoint()); } var tokens = parser.RemainingTokens(); var role = DiagramEdgeRole.None; try { role = (DiagramEdgeRole)Int32.Parse(tokens[tokens.Length - 1].After(1), NumberStyles.HexNumber); } catch { } if (role != DiagramEdgeRole.None) { var edge = new DiagramEdge(source, target, role, null); edge.ComputedPath = points; diagram.Edges.Add(edge); } } parser.Close(); }
// private constructor private DotParser(string path, DiagramCanvas diagram) { var reader = new StreamReader(path); var buffer = reader.ReadToEnd(); reader.Close(); _diagram = diagram; var size = _parseRect(buffer.FindFirst(new Regex(@"bb=""([\d\,]+)"""))).Size; _diagram.ComputedSize = size; diagram.Blocks.Where(b => _isVisible(b)).Apply(b => b.ComputedBounds = Rect.Empty); buffer = buffer.ReplaceAll(_reEdgePattern, _parseEdge); buffer = buffer.ReplaceAll(_reNodePattern, _parseNode); }
public static void Parse(string path, DiagramCanvas diagram) { var parser = new DotParser(path, diagram); }
/// <summary>Creates a new <see cref="DiagramNode"/> instance.</summary> public DiagramNode(DiagramCanvas canvas, long id, BplClass bplClass) : base(canvas, id) { Assumption.NotNull(bplClass); Class = bplClass; }
/// <summary>Creates a new <see cref="DiagramBlock"/> instance.</summary> public DiagramBlock(DiagramCanvas canvas, long id, BplNamespace bplNamespace) : base(canvas, id) { Namespace = bplNamespace; _nodes = new HashSet<DiagramNode>(); Nodes = new ReadOnlySet<DiagramNode>(_nodes); }