예제 #1
0
      /// <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;
      }
예제 #2
0
 /// <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);
    }
 }
예제 #3
0
 // Invoked to initially draw the edge
 internal void Draw(DiagramCanvas diagram) {
    diagram.EdgesLayer.Children.Add(this);
    LayoutChanged();
 }
예제 #4
0
 /// <summary>Creates a new <see cref="DiagramSprite"/> instance.</summary>
 public DiagramSprite(DiagramCanvas canvas, long id) {
    Canvas = canvas;
    Id = id;
    Visibility = ComputedVisibility = Visibility.Hidden;
 }
예제 #5
0
      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);
      }
예제 #6
0
         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();
         }
예제 #7
0
         // 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);
         }
예제 #8
0
 public static void Parse(string path, DiagramCanvas diagram) {
    var parser = new DotParser(path, diagram);
 }
예제 #9
0
 /// <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;
 }
예제 #10
0
 /// <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);
 }