public void PopulatePanel(Graphics g)
        {
            // add shapes
            foreach (IVertex v in VisitedGraph.Vertices)
            {
                // do not add vertex if already in panel
                if (VertexShapes.Contains(v))
                {
                    continue;
                }
                AttachShape(v);
            }

            // udpate shape sizes if possible and build size dictionary
            NetronGraphvizLayouter layout = new NetronGraphvizLayouter(this);

            layout.Layouter.DpiX          = g.DpiX;
            layout.Layouter.DpiY          = g.DpiY;
            layout.Layouter.RankDirection = this.RankDirection;
            foreach (DictionaryEntry de in this.ShapeVertices)
            {
                if (de.Key is Netron.Shape)
                {
                    Netron.Shape shape = (Netron.Shape)de.Key;
                    layout.VertexSizes[(IVertex)de.Value] = shape.Size;
                }
                else
                {
                    throw new Exception("Shapes must derive from Netron.Shape");
                }
            }
            layout.Compute();
            layout.PositionVertices();

            foreach (IEdge e in VisitedGraph.Edges)
            {
                // check if edge alreay in graph
                if (EdgeConnections.Contains(e))
                {
                    continue;
                }
                AttachConnection(layout, e);
            }

            // reposition connections
            //	layout.PositionConnections();

            // redraw panel
            this.Panel.Invalidate();
            this.graphDirty = false;
        }
        public void Connect(
            IEdge e,
            Netron.Connection conn,
            Netron.Shape source,
            Netron.Shape target
            )
        {
            // get ports
            EdgeKeysEventArgs args = (EdgeKeysEventArgs)layouter.EdgeArgs[e];

            if (args.Keys.Count < 2)
            {
                throw new ArgumentException("not enough keys");
            }
            // find best from
            conn.From = FindNearestConnector(source, args.Keys[0]);
            conn.To   = FindNearestConnector(target, args.Keys[args.Keys.Count - 1]);
        }
        public Connector FindNearestConnector(Netron.Shape shape, PointF p)
        {
            Connector best     = null;
            double    distBest = double.MaxValue;
            double    dist;

            foreach (Connector c in shape.Connectors)
            {
                dist = PointMath.SqrDistance(shape.ConnectionPoint(c), p);
                if (dist < distBest)
                {
                    distBest = dist;
                    best     = c;
                }
            }

            if (best == null)
            {
                throw new Exception("could not find port");
            }

            return(best);
        }