/// <summary> /// Draws a partially defined graph edge</summary> /// <param name="fromNode">Source node, or null</param> /// <param name="fromRoute">Source route, or null</param> /// <param name="toNode">Destination node, or null</param> /// <param name="toRoute">Destination route, or null</param> /// <param name="label">Edge label</param> /// <param name="endPoint">Endpoint to substitute for source or destination, if either is null</param> /// <param name="g">Graphics object</param> public override void Draw( TNode fromNode, BoundaryRoute fromRoute, TNode toNode, BoundaryRoute toRoute, string label, Point endPoint, D2dGraphics g) { // put endpoint into statechart space var inverse = g.Transform; inverse.Invert(); PointF end = Matrix3x2F.TransformPoint(inverse, endPoint); PointF p1; PointF normal1; if (fromNode != null) { p1 = ParameterToPoint(fromNode.Bounds, fromRoute.Position, out normal1); } else { p1 = end; normal1 = new Point(); } PointF p4; PointF normal2; if (toNode != null) { p4 = ParameterToPoint(toNode.Bounds, toRoute.Position, out normal2); } else { p4 = end; normal2 = new Point(); } PointF p2, p3; float d = GetTransitionPoints(p1, normal1, p4, normal2, out p2, out p3); DrawEdgeSpline(p1, p2, p3, p4, d, m_theme.OutlineBrush, g); if (!string.IsNullOrEmpty(label)) { BezierCurve2F curve = new BezierCurve2F(p1, p2, p3, p4); Vec2F midpoint = curve.Evaluate(0.5f); g.DrawText(label, m_centerText, new PointF(midpoint.X, midpoint.Y), m_theme.TextBrush); } }
/// <summary> /// Draws a partially defined graph edge</summary> /// <param name="fromNode">Source node, or null</param> /// <param name="fromRoute">Source route, or null</param> /// <param name="toNode">Destination node, or null</param> /// <param name="toRoute">Destination route, or null</param> /// <param name="label">Edge label</param> /// <param name="endPoint">Endpoint to substitute for source or destination, if either is null</param> /// <param name="g">Graphics object</param> public override void Draw( TNode fromNode, BoundaryRoute fromRoute, TNode toNode, BoundaryRoute toRoute, string label, Point endPoint, Graphics g) { // put endpoint into statechart space endPoint = GdiUtil.InverseTransform(g.Transform, endPoint); Point p1; Point normal1; if (fromNode != null) { p1 = ParameterToPoint(fromNode.Bounds, fromRoute.Position, out normal1); } else { p1 = endPoint; normal1 = new Point(); } Point p4; Point normal2; if (toNode != null) { p4 = ParameterToPoint(toNode.Bounds, toRoute.Position, out normal2); } else { p4 = endPoint; normal2 = new Point(); } Point p2, p3; float d = GetTransitionPoints(p1, normal1, p4, normal2, out p2, out p3); DrawEdgeSpline(p1, p2, p3, p4, d, m_theme.OutlinePen, g); BezierCurve2F curve = new BezierCurve2F(p1, p2, p3, p4); Vec2F midpoint = curve.Evaluate(0.5f); midpoint.X += 2; g.DrawString(label, m_theme.Font, m_theme.TextBrush, new PointF(midpoint.X, midpoint.Y)); }
/// <summary> /// Finds node and/or edge hit by the given point</summary> /// <param name="graph">Graph to test</param> /// <param name="priorityEdge">Graph edge to test before others</param> /// <param name="p">Point to test</param> /// <param name="g">Graphics object</param> /// <returns>Hit record containing node and/or edge hit by the given point</returns> public override GraphHitRecord <TNode, TEdge, BoundaryRoute> Pick( IGraph <TNode, TEdge, BoundaryRoute> graph, TEdge priorityEdge, Point p, Graphics g) { int tolerance = m_theme.PickTolerance; TNode pickedNode = null; TEdge pickedEdge = null; BoundaryRoute fromRoute = null; BoundaryRoute toRoute = null; Vec2F v = new Vec2F(p.X, p.Y); if (priorityEdge != null && Pick(priorityEdge, v)) { pickedEdge = priorityEdge; } else { foreach (TEdge edge in graph.Edges.Reverse()) { if (Pick(edge, v)) { pickedEdge = edge; break; } } } foreach (TNode state in graph.Nodes.Reverse()) { Rectangle bounds = state.Bounds; bounds.Inflate(tolerance, tolerance); if (bounds.Contains(p)) { pickedNode = state; float position = PointToParameter(bounds, p); bounds.Inflate(-2 * tolerance, -2 * tolerance); bool onEdge = !bounds.Contains(p); if (pickedEdge == null) { if (onEdge) { // edge of node can be source or destination fromRoute = new BoundaryRoute(position); toRoute = new BoundaryRoute(position); } } else // hit on edge and node { if (onEdge) { if (pickedEdge.FromNode == pickedNode) { fromRoute = new BoundaryRoute(position); } else if (pickedEdge.ToNode == pickedNode) { toRoute = new BoundaryRoute(position); } } } break; } } IComplexState <TNode, TEdge> complexState = pickedNode as IComplexState <TNode, TEdge>; if (complexState != null && pickedEdge == null) { Rectangle bounds = pickedNode.Bounds; Rectangle labelBounds = new Rectangle( bounds.X + CornerRadius, bounds.Y + Margin, bounds.Width - 2 * CornerRadius, m_theme.Font.Height); if (labelBounds.Contains(p)) { DiagramLabel label = new DiagramLabel(labelBounds, TextFormatFlags.SingleLine); return (new GraphHitRecord <TNode, TEdge, BoundaryRoute>(pickedNode, label)); } } return (new GraphHitRecord <TNode, TEdge, BoundaryRoute>(pickedNode, pickedEdge, fromRoute, toRoute)); }