コード例 #1
0
        /// <summary>
        /// Callback that actually creates the node and its business object
        /// </summary>
        private INode CreateNodeCallback(IInputModeContext context, IGraph graph, PointD location, INode parent)
        {
            RectD newBounds = RectD.FromCenter(location, graph.NodeDefaults.Size);
            var   node      = graph.CreateNode(newBounds, graph.NodeDefaults.GetStyleInstance(), new MyBusinessObject(0.3));

            return(node);
        }
        /// <summary>
        /// Aggregates the nodes to a new aggregation node.
        /// </summary>
        /// <remarks>
        /// Adds a label with the number of aggregated nodes and adds labels
        /// to all created aggregation edges with the number of replaced original edges.
        /// </remarks>
        private void Aggregate <TKey>(IList <INode> nodes, TKey key, Func <TKey, INodeStyle> styleFactory)
        {
            var size   = Graph.NodeDefaults.Size * (1 + nodes.Count * 0.2);
            var layout = RectD.FromCenter(PointD.Origin, size);

            AggregateGraph.Aggregate(new ListEnumerable <INode>(nodes), layout, styleFactory(key));
        }
コード例 #3
0
        /// <summary>
        /// Creates a GraphBuilder instance that's preconfigured with our demo's styles.
        /// </summary>
        internal static (GraphBuilder, NodesSource <INeo4jNode>, EdgesSource <IRelationship>) CreateGraphBuilder(GraphControl graphControl, IGraph graph, List <INeo4jNode> nodes, List <IRelationship> edges)
        {
            var builder     = new GraphBuilder(graph);
            var nodesSource = builder.CreateNodesSource(nodes, n => n.Id);

            nodesSource.NodeCreator.TagProvider = n => n;
            var nodeStyle = new Neo4JNodeStyle();

            nodesSource.NodeCreator.Defaults.Style = nodeStyle;
            nodesSource.NodeCreator.Defaults.Size  = new SizeD(240, 80);
            var edgesSource = builder.CreateEdgesSource(edges, e => e.StartNodeId, e => e.EndNodeId, e => e.Id);

            edgesSource.EdgeCreator.Defaults.Style = new BezierEdgeStyle {
                TargetArrow = Arrows.Default
            };
            var labelBinding = edgesSource.EdgeCreator.CreateLabelBinding(item => item.Type);

            labelBinding.Defaults.LayoutParameter = new EdgeSegmentLabelModel().CreateParameterFromSource(0, 0, EdgeSides.AboveEdge);

            builder.NodeCreated +=
                (sender, e) => {
                // Ensure that nodes have the correct size
                e.Graph.SetNodeLayout(e.Item, RectD.FromCenter(e.Item.Layout.GetCenter(), nodeStyle.GetPreferredSize(e.Item)));
            };
            return(builder, nodesSource, edgesSource);
        }
コード例 #4
0
        private VisualGroup CreateVisual(CanvasControl canvas)
        {
            RectD rect = canvas.ContentRect;
            ContextConfigurator configurator = new ContextConfigurator(rect)
            {
                Margins = new InsetsD(0, 0, 0, 0)
            };

            // scale down if necessary
            if (ActualHeight > 0 && ActualHeight > 0)
            {
                if (ActualHeight < rect.Height || ActualWidth < rect.Width)
                {
                    configurator.Scale = Math.Min(ActualWidth / rect.Width, ActualHeight / rect.Height);
                }
                RectD bounds = RectD.FromCenter(rect.Center,
                                                new SizeD(ActualWidth, ActualHeight) * (1 / configurator.Scale));
                configurator.WorldBounds = bounds;
            }

            IRenderContext vc        = configurator.CreateRenderContext(canvas);
            Transform      transform = configurator.CreateWorldToIntermediateTransform();
            Visual         visual    = canvas.ExportContent(vc);

            return(new VisualGroup {
                Children = { visual }, Clip = Clip, Transform = transform
            });
        }
コード例 #5
0
        /// <summary>
        /// Creates a node of the specified type.
        /// </summary>
        /// <remarks>
        /// The method will specify the ports that the node should have based on its type.
        /// </remarks>
        private void CreateNode(IGraph graph, PointD location, LogicGateType type, string label, SizeD?size = null)
        {
            RectD newBounds = RectD.FromCenter(location, graph.NodeDefaults.Size);
            INode node;

            if (type >= LogicGateType.Timer)
            {
                node = graph.CreateNode(RectD.FromCenter(location, (SizeD)size), new ShapeNodeStyle {
                    Pen = new Pen(Brushes.Black, 2)
                });
            }
            else
            {
                node = graph.CreateNode(newBounds, new LogicGateNodeStyle {
                    GateType = type
                });
            }

            graph.AddLabel(node, label, InteriorLabelModel.Center);

            var portDescriptors = PortDescriptor.CreatePortDescriptors(type);

            // use relative port locations
            var model = new FreeNodePortLocationModel();

            // add ports for all descriptors using the descriptor as the tag of the port
            foreach (var descriptor in portDescriptors)
            {
                // use the descriptor's location as offset
                var portLocationModelParameter = model.CreateParameter(PointD.Origin, new PointD(descriptor.X, descriptor.Y));
                graph.AddPort(node, portLocationModelParameter, tag: descriptor);
            }
        }
コード例 #6
0
        /// <summary>
        /// Aggregates the <paramref name="aggregate"/> as well as all its children recursively.
        /// </summary>
        /// <remarks>
        /// Can be used to apply the initial aggregation. If this is not the initial aggregation run, it will reuse existing
        /// aggregation nodes.
        /// </remarks>
        /// <param name="aggregate">The "root" aggregate.</param>
        /// <returns>The aggregation node representing the passed <paramref name="aggregate"/></returns>
        public INode AggregateRecursively(NodeAggregation.Aggregate aggregate)
        {
            if (aggregate.Children.Count == 0)
            {
                return(aggregate.Node);
            }

            PointD originalCenter;

            if (aggregateToNode.TryGetValue(aggregate, out var node))
            {
                originalCenter = node.Layout.GetCenter();
                var aggregationInfo = (AggregationNodeInfo)node.Tag;
                if (aggregationInfo.IsAggregated)
                {
                    return(node);
                }
                else
                {
                    AggregateGraph.Separate(node);
                }
            }
            else
            {
                originalCenter = PointD.Origin;
            }

            var nodesToAggregate = aggregate.Children.Select(AggregateRecursively).ToList();

            if (aggregate.Node != null)
            {
                nodesToAggregate.Add(aggregate.Node);
            }

            var size            = 30 + Math.Sqrt(aggregate.DescendantWeightSum) * 4;
            var layout          = RectD.FromCenter(originalCenter, new SizeD(size, size));
            var aggregationNode =
                AggregateGraph.Aggregate(new ListEnumerable <INode>(nodesToAggregate), layout, AggregationNodeStyle);

            aggregateToNode[aggregate] = aggregationNode;
            aggregationNode.Tag        = new AggregationNodeInfo(aggregate, true);

            if (aggregate.Node != null)
            {
                placeholderMap[aggregate.Node] = aggregationNode;
                CopyLabels(aggregate.Node, aggregationNode);
            }
            else
            {
                var maxChild = GetMostImportantDescendant(aggregate);
                if (maxChild.Node != null && maxChild.Node.Labels.Any())
                {
                    AggregateGraph.AddLabel(aggregationNode, $"({maxChild.Node.Labels[0].Text}, …)",
                                            FreeNodeLabelModel.Instance.CreateDefaultParameter(), DescendantLabelStyle);
                }
            }

            return(aggregationNode);
        }
コード例 #7
0
        /// <summary>
        /// Callback used by <see cref="GraphEditorInputMode"/> to actually create a node upon a click.
        /// </summary>
        /// <remarks>
        /// This method creates a dummy business object and associated it with a newly created node.
        /// </remarks>
        private INode CreateNode(IInputModeContext context, IGraph graph, PointD location, INode parent)
        {
            Customer c          = new Customer("Sample Customer", "Your Computer", new Random((int)DateTime.Now.TimeOfDay.TotalMilliseconds).Next(99999));
            var      simpleNode = new SimpleNode {
                Tag = c, Style = customerNodeStyle, Layout = new MutableRectangle(0, 0, 10, 10)
            };
            var preferredSize = customerNodeStyle.GetPreferredSize(graphControl.CreateRenderContext(), simpleNode);

            return(graph.CreateNode(RectD.FromCenter(location, preferredSize), customerNodeStyle, c));
        }
コード例 #8
0
        /// <summary>
        /// Callback that actually creates the node and its business object
        /// </summary>
        private INode CreateNodeCallback(IInputModeContext context, IGraph graph, PointD location, INode parent)
        {
            RectD newBounds = RectD.FromCenter(location, graph.NodeDefaults.Size);
            var   node      = graph.CreateNode(newBounds);

            node.Tag = new LayerConstraintsInfo
            {
                Value       = rand.Next(0, 7),
                Constraints = rand.NextDouble() < 0.9
            };
            return(node);
        }
コード例 #9
0
        public IVisual CreateVisual(IRenderContext context)
        {
            rectangle = new MutableRectangle(RectD.FromCenter(Center, new SizeD(PageWidth + Margin, PageHeight + Margin)));
            var rectVisual = new RectangleVisual(rectangle)
            {
                Pen = new Pen(Color.Black, 1)
                {
                    DashStyle = DashStyle.Dash
                }
            };

            return(rectVisual);
        }
コード例 #10
0
        /// <summary>
        /// Callback that actually creates the node and its business object
        /// </summary>
        private INode CreateNodeCallback(IInputModeContext context, IGraph graph, PointD location, INode parent)
        {
            RectD newBounds = RectD.FromCenter(location, graph.NodeDefaults.Size);
            // create a new node
            var node = graph.CreateNode(newBounds);

            // set the node tag to a new random sequence constraints
            node.Tag = new SequenceConstraintsInfo {
                Value       = rand.Next(0, 7),
                Constraints = rand.NextDouble() < 0.9
            };
            return(node);
        }
コード例 #11
0
        /// <summary>
        /// Constructs the yFiles graph from the database results.
        /// </summary>
        /// <param name="nodes">A list of nodes from the database.</param>
        /// <param name="edges">A list of edges from the database.</param>
        /// <param name="clearGraph">A value indicating whether the current graph should be replaced.</param>
        /// <param name="initialLocation">The initial location of newly-created nodes.</param>
        private async Task BuildGraphAsync(List <INeo4jNode> nodes, List <IRelationship> edges, bool clearGraph, PointD initialLocation)
        {
            if (graphBuilder == null || clearGraph)
            {
                Graph.Clear();
                this.nodes = nodes;
                this.edges = edges;
                (graphBuilder, nodesSource, edgesSource) = CreateGraphBuilder(graphControl, Graph, nodes, edges);
                // Move new nodes back in z-order to make it look like they show up from underneath the neighboring node
                graphBuilder.NodeCreated += (sender, e) => graphControl.GraphModelManager.GetCanvasObject(e.Item).ToBack();
            }
            else
            {
                // Add new data to existing data
                nodes = this.nodes.Concat(nodes).Distinct(IdEqualityComparer <INeo4jNode> .Instance).ToList();
                edges = this.edges.Concat(edges).Distinct(IdEqualityComparer <IRelationship> .Instance).ToList();
                this.nodes.Clear();
                this.nodes.AddRange(nodes);
                this.edges.Clear();
                this.edges.AddRange(edges);
            }

            nodesSource.NodeCreator.LayoutProvider = n => RectD.FromCenter(initialLocation, Graph.NodeDefaults.Size);

            // Update the graph and detect which nodes have been added
            var existingNodes = new HashSet <INode>(Graph.Nodes);
            var existingEdges = new HashSet <IEdge>(Graph.Edges);

            graphBuilder.UpdateGraph();

            var newNodes = Graph.Nodes.Except(existingNodes).ToList();
            var newEdges = Graph.Edges.Except(existingEdges).ToList();

            foreach (var node in newNodes)
            {
                incrementalNodes.Add(node);
            }
            foreach (var edge in newEdges)
            {
                incrementalNodes.Add(edge.GetSourceNode());
                incrementalNodes.Add(edge.GetTargetNode());
            }

            loadingIndicator.Visibility = Visibility.Collapsed;

            // Layout the graph if there are new items
            if (newNodes.Count > 0 || newEdges.Count > 0)
            {
                await ApplyLayout(incrementalNodes);
            }
        }
コード例 #12
0
        /// <summary>
        /// Separates an aggregated aggregation node and replaces it by a new aggregation node.
        /// </summary>
        /// <remarks>
        /// Creates hierarchy edges between the new aggregation node and its children.
        /// </remarks>
        /// <param name="node">The node.</param>
        /// <returns>The nodes affected by this operation. The created aggregation node is always the first item.</returns>
        public IListEnumerable <INode> Separate(INode node)
        {
            var aggregationInfo = (AggregationNodeInfo)node.Tag;
            var aggregate       = aggregationInfo.Aggregate;
            var aggregatedItems = AggregateGraph.GetAggregatedItems(node)
                                  .Where(n => n != aggregate.Node)
                                  .Cast <INode>().ToList();

            AggregateGraph.Separate(node);

            var nodesToAggregate = aggregate.Node != null
          ? new ListEnumerable <INode>(new List <INode> {
                aggregate.Node
            })
          : ListEnumerable <INode> .Empty;
            var aggregationNode = AggregateGraph.Aggregate(nodesToAggregate, node.Layout.ToRectD(), AggregationNodeStyle);

            foreach (var child in aggregatedItems)
            {
                AggregateGraph.CreateEdge(aggregationNode, child, HierarchyEdgeStyle, true);
                AggregateGraph.SetNodeLayout(child,
                                             RectD.FromCenter(aggregationNode.Layout.GetCenter(), child.Layout.ToSizeD()));
                ReplaceEdges(child);
            }

            aggregationInfo.IsAggregated = false;
            aggregateToNode[aggregate]   = aggregationNode;
            aggregationNode.Tag          = aggregationInfo;

            var affectedNodes = new List <INode> {
                aggregationNode
            };

            affectedNodes.AddRange(aggregatedItems);

            if (aggregate.Parent != null && aggregateToNode.TryGetValue(aggregate.Parent, out var parentNode))
            {
                AggregateGraph.CreateEdge(parentNode, aggregationNode, HierarchyEdgeStyle, true);
                affectedNodes.Add(parentNode);
            }

            if (aggregate.Node != null)
            {
                placeholderMap[aggregate.Node] = aggregationNode;
                CopyLabels(aggregate.Node, aggregationNode);
                ReplaceEdges(aggregationNode);
            }

            return(new ListEnumerable <INode>(affectedNodes));
        }
コード例 #13
0
        // Creates a node and sets it's correct size
        private INode CreateNode(IInputModeContext context, IGraph graph, PointD location, INode parent)
        {
            INode node = graph.CreateNode(location);

            node.Tag = CreateDefaultClassInfo();
            var style = node.Style as NodeControlNodeStyle;

            if (style != null)
            {
                SizeD size = style.GetPreferredSize(graphControl.CreateRenderContext(), node);
                graph.SetNodeLayout(node, RectD.FromCenter(location, new SizeD(120, size.Height)));
            }
            return(node);
        }
コード例 #14
0
        /// <summary>
        /// Sets the original node bounds according to the given anchor location and size.
        /// </summary>
        private RectD SetNodeLocationAndSize(IInputModeContext inputModeContext, PointD anchor, SizeD size)
        {
            var graph = inputModeContext.GetGraph();

            if (graph == null)
            {
                return(RectD.Empty);
            }
            var orientedRectangle = new OrientedRectangle(anchor.X, anchor.Y, size.Width, size.Height,
                                                          initialLayout.UpX, initialLayout.UpY);
            var center = orientedRectangle.GetCenter();

            var layout = RectD.FromCenter(center, size);

            graph.SetNodeLayout(node, layout);
            return(layout);
        }
コード例 #15
0
        /// <summary>
        /// Initializes the graph instance setting default styles
        /// and creating a small sample graph.
        /// </summary>
        protected virtual void InitializeGraph()
        {
            IGraph graph = graphControl.Graph;

            // set the style as the default for all new nodes
            graph.NodeDefaults.Style = defaultStyle;
            graph.NodeDefaults.Size  = new SizeD(100, 60);

            DefaultLabelStyle labelStyle = new DefaultLabelStyle();

            labelStyle.Typeface        = new Typeface("Arial");
            labelStyle.BackgroundBrush = Brushes.LightBlue;

            // set the style as the default for all new node labels
            graph.NodeDefaults.Labels.Style = labelStyle;

            graph.CreateNode(RectD.FromCenter(new PointD(200, 100), graph.NodeDefaults.Size), graph.NodeDefaults.GetStyleInstance(), new MyBusinessObject(0.3));
        }
コード例 #16
0
        /// <summary>
        /// Initializes the graph instance setting default styles
        /// and creating a small sample graph.
        /// </summary>
        protected virtual void InitializeGraph()
        {
            IGraph graph = graphControl.Graph;

            // set the style as the default for all new nodes
            graph.NodeDefaults.Style = defaultStyle;
            graph.NodeDefaults.Size  = new SizeD(100, 60);

            DefaultLabelStyle labelStyle = new DefaultLabelStyle();
            Font font = new Font(FontFamily.GenericSansSerif, 12, GraphicsUnit.Pixel);

            labelStyle.Font            = font;
            labelStyle.BackgroundBrush = Brushes.LightBlue;

            // set the style as the default for all new node labels
            graph.NodeDefaults.Labels.Style = labelStyle;

            graph.CreateNode(RectD.FromCenter(new PointD(200, 100), graph.NodeDefaults.Size), graph.NodeDefaults.GetStyleInstance(), new MyBusinessObject(0.3));
        }
コード例 #17
0
        private NodeCreationCallback GetNodeCreator(NodeCreationCallback nodeCreator)
        {
            return((context, graph, location, parent) => {
                INode paletteNode = styleListBox.SelectedItem as INode;
                if (paletteNode != null)
                {
                    if (paletteNode.Tag == null || !paletteNode.Tag.ToString().EndsWith("Label Container"))
                    {
                        INode newNode = nodeCreator(context, graph, location, parent);
                        graph.SetStyle(newNode, paletteNode.Style);
                        graph.SetNodeLayout(newNode, RectD.FromCenter(location, paletteNode.Layout.ToSizeD()));
                        graph.SetIsGroupNode(newNode, paletteNode.Style is PanelNodeStyle);
                        foreach (var label in paletteNode.Labels)
                        {
                            graph.AddLabel(newNode, label.Text, label.LayoutParameter, label.Style);
                        }
                        return newNode;
                    }
                }

                return null;
            });
        }
コード例 #18
0
        /// <summary>
        /// Paint the node style representation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void nodeStyleListBox_DrawItem(object sender, DrawItemEventArgs e)
        {
            ListBox listBox = (ListBox)sender;
            int     i       = e.Index;
            INode   node    = (INode)listBox.Items[i];

            node = new SimpleNode {
                Labels = node.Labels,
                Layout = node.Layout,
                Style  = node.Style,
                Tag    = node.Tag
            };
            if (node.Layout.Height > 50)
            {
                ((SimpleNode)node).Layout = RectD.FromCenter(node.Layout.GetCenter(), new SizeD(20, 30));
            }

            Rectangle bounds = e.Bounds;
            Rectangle insets = Rectangle.FromLTRB(5, 5, 5, 25);

            Graphics      g       = e.Graphics;
            SmoothingMode oldMode = g.SmoothingMode;
            Region        oldClip = g.Clip;

            // in .net 3.5 there are repaint issues - none of the below seems to help, there
            // are still sometimes background rendering artifacts left over.
            g.IntersectClip(bounds);
            g.FillRegion(new SolidBrush(e.BackColor), g.Clip);
            g.Clear(e.BackColor);
            e.DrawBackground();

            var sx = (float)((bounds.Width - insets.Left - insets.Right) / node.Layout.Width);
            var sy = (float)((bounds.Height - insets.Top - insets.Bottom) / node.Layout.Height);

            if (sx > 0 && sy > 0)
            {
                var transform = g.Transform;
                g.SmoothingMode = SmoothingMode.HighQuality;

                g.TranslateTransform((float)(bounds.X + insets.Left), (float)(bounds.Y + insets.Top));
                g.ScaleTransform(Math.Min(sx, sy), Math.Min(sx, sy));
                g.TranslateTransform((float)(-node.Layout.X), (float)(-node.Layout.Y));

                //Get the renderer from the style, this requires the dummy node instance.
                var renderContext = new RenderContext(g, null)
                {
                    ViewTransform = g.Transform, WorldTransform = g.Transform
                };
                node.Style.Renderer.GetVisualCreator(node, node.Style).CreateVisual(renderContext).Paint(renderContext, g);
                var lgns = node.Style as LogicGateNodeStyle;
                if (lgns != null)
                {
                    g.DrawString(lgns.GateType.ToString(), new Font("Arial", 8.25f), Brushes.Black, -10, 20);
                }
                else if (node.Labels.Any())
                {
                    g.DrawString(node.Labels.First().Text.Replace("\n", " "), new Font("Arial", 8.25f), Brushes.Black, -10, 20);
                }
                g.Transform     = transform;
                g.SmoothingMode = oldMode;
            }

            g.Clip = oldClip;
            e.DrawFocusRectangle();
        }
コード例 #19
0
 public IVisual UpdateVisual(IRenderContext context, IVisual oldVisual)
 {
     rectangle.Reshape(RectD.FromCenter(Center, new SizeD(PageWidth + Margin, PageHeight + Margin)));
     return(oldVisual);
 }
コード例 #20
0
 /// <summary>
 /// Calculates the bounds of this port.
 /// </summary>
 /// <remarks>
 /// These are also used for arranging the visual, hit testing, visibility testing, and marquee box tests.
 /// </remarks>
 protected override RectD GetBounds(ICanvasContext context, IPort port)
 {
     return(RectD.FromCenter(port.GetLocation(), new SizeD(Width, Height)));
 }
コード例 #21
0
 public override void SetBounds(IRectangle bounds)
 {
     base.SetBounds(RectD.FromCenter(bounds.GetCenter(), combinedSize));
 }