private void UpdateControl(D2dAdaptableControl source, D2dAdaptableControl target, Point cpt) { target.Context = source.Context; if (target.Context == null) { return; } // transform current mouse point to graph space. var srcXform = source.As <ITransformAdapter>(); Matrix3x2F mtrx = Matrix3x2F.Invert(srcXform.Transform); var gpt = Matrix3x2F.TransformPoint(mtrx, cpt); var targetXform = target.As <ITransformAdapter>(); var csz = target.ClientSize; PointF translation = new PointF(csz.Width / 2 - gpt.X * targetXform.Scale.X, csz.Height / 2 - gpt.Y * targetXform.Scale.Y); targetXform.Translation = translation; var edgeEditor = source.As <D2dGraphEdgeEditAdapter <Module, Connection, ICircuitPin> >(); m_activeEdgeEditor = (edgeEditor != null && edgeEditor.IsDraggingEdge) ? edgeEditor : null; target.Invalidate(); }
protected override void OnMouseDown(object sender, MouseEventArgs e) { if (e.Button != MouseButtons.Left || !IsContextValid()) { return; } var sourceControl = m_birdEyeView.m_sourceControl; var srcXformAdapter = sourceControl.Cast <ITransformAdapter>(); var srcInvXform = Matrix3x2F.Invert(srcXformAdapter.Transform); var grect = Matrix3x2F.Transform(srcInvXform, sourceControl.ClientRectangle); var inxXform = Matrix3x2F.Invert(m_transformAdapter.Transform); var gpt = Matrix3x2F.TransformPoint(inxXform, e.Location); if (!grect.Contains(gpt)) { var srcScale = srcXformAdapter.Scale; float gcx = grect.X + grect.Width / 2; float gcy = grect.Y + grect.Height / 2; grect.X += gpt.X - gcx; grect.Y += gpt.Y - gcy; float tx = -grect.X * srcScale.X; float ty = -grect.Y * srcScale.Y; srcXformAdapter.Translation = new PointF(tx, ty); } m_hitGpt.X = gpt.X - grect.X; m_hitGpt.Y = gpt.Y - grect.Y; base.OnMouseDown(sender, e); AdaptedControl.Capture = true; }
/// <summary> /// Transforms rectangle</summary> /// <param name="matrix">Matrix representing transform</param> /// <param name="r">Rectangle</param> /// <returns>Transformed rectangle</returns> public static RectangleF Transform(Matrix3x2F matrix, RectangleF r) { s_tempPtsF[0] = new PointF(r.Left, r.Top); s_tempPtsF[1] = new PointF(r.Right, r.Bottom); s_tempPtsF[0] = Matrix3x2F.TransformPoint(matrix, s_tempPtsF[0]); s_tempPtsF[1] = Matrix3x2F.TransformPoint(matrix, s_tempPtsF[1]); return(MakeRectangle(s_tempPtsF[0], s_tempPtsF[1])); }
private void control_MouseWheel(object sender, MouseEventArgs e) { if (!AdaptedControl.ClientRectangle.Contains(e.Location)) { return; } if (e.Button != MouseButtons.None || !IsContextValid()) { return; } // apply transformation to source control. var sourceControl = m_birdEyeView.m_sourceControl; var srcXformAdapter = sourceControl.Cast <ITransformAdapter>(); var srcInvXform = Matrix3x2F.Invert(srcXformAdapter.Transform); var grect = Matrix3x2F.Transform(srcInvXform, sourceControl.ClientRectangle); var inxXform = Matrix3x2F.Invert(m_transformAdapter.Transform); var gpt = Matrix3x2F.TransformPoint(inxXform, e.Location); if (!grect.Contains(gpt)) { return; } // zoom at the center of the grect. gpt.X = grect.X + grect.Width / 2; gpt.Y = grect.Y + grect.Height / 2; // transform gpt to client space of sourcecontrol. var srcCpt = Matrix3x2F.TransformPoint(srcXformAdapter.Transform, gpt); PointF translation = srcXformAdapter.Translation; PointF scale = srcXformAdapter.Scale; PointF scaleCenterStart = new PointF( (srcCpt.X - translation.X) / scale.X, (srcCpt.Y - translation.Y) / scale.Y); float delta = 1.0f + e.Delta / 1200.0f; scale = new PointF( scale.X * delta, scale.Y * delta); // constrain scale before calculating translation to maintain scroll center position scale = srcXformAdapter.ConstrainScale(scale); translation = new PointF( srcCpt.X - scaleCenterStart.X * scale.X, srcCpt.Y - scaleCenterStart.Y * scale.Y); srcXformAdapter.SetTransform( scale.X, scale.Y, translation.X, translation.Y); }
/// <summary> /// Transforms point by inverse transform</summary> /// <param name="matrix">Matrix representing transform</param> /// <param name="p">Point</param> /// <returns>Inverse transformed point</returns> public static Point InverseTransform(Matrix3x2F matrix, Point p) { Matrix3x2F inverse = matrix; inverse.Invert(); s_tempPtsF[0] = p; s_tempPtsF[0] = Matrix3x2F.TransformPoint(inverse, s_tempPtsF[0]); return(new Point((int)s_tempPtsF[0].X, (int)s_tempPtsF[0].Y)); }
/// <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> /// Gets the bounding rectangle of all circuit items in client coordinates</summary> /// <returns>Bounding rectangle of all circuit items in client coordinates</returns> public Rectangle GetBounds() { if (m_graph == null) { return(Rectangle.Empty); } IEnumerable <object> items = m_graph.Nodes; var annoDiagram = m_graph.As <IAnnotatedDiagram>(); if (annoDiagram != null) { items = items.Concat(annoDiagram.Annotations); } Rectangle bounds = GetBounds(items); if (DomNode.Is <Group>()) { // include group pins y range var group = DomNode.Cast <Group>(); int yMin = int.MaxValue; int yMax = int.MinValue; foreach (var pin in group.InputGroupPins.Concat(group.OutputGroupPins)) { var grpPin = pin.Cast <GroupPin>(); if (grpPin.Bounds.Y < yMin) { yMin = grpPin.Bounds.Y; } if (grpPin.Bounds.Y > yMax) { yMax = grpPin.Bounds.Y; } } // transform y range to client space if (yMin != int.MaxValue && yMax != int.MinValue) { var transformAdapter = m_control.Cast <ITransformAdapter>(); var minPt = Matrix3x2F.TransformPoint(transformAdapter.Transform, new PointF(0, yMin)); var maxPt = Matrix3x2F.TransformPoint(transformAdapter.Transform, new PointF(0, yMax)); yMin = (int)minPt.Y; yMax = (int)maxPt.Y; int width = bounds.Width; int height = yMax - yMin + 1; bounds = Rectangle.Union(bounds, new Rectangle(bounds.X, yMin, width, height)); } } return(bounds); }
private void m_magnifier_Painting(object sender, EventArgs e) { var d2dControl = (D2dAdaptableControl)sender; if (d2dControl.Context != null) { var saveXform = d2dControl.D2dGraphics.Transform; var dragEdge = m_activeEdgeEditor != null?m_activeEdgeEditor.GetDraggingEdge() : null; if (dragEdge != null) { PointF start = dragEdge.StartPoint; PointF end = dragEdge.EndPoint; if (dragEdge.FromRoute == null) { start = Matrix3x2F.TransformPoint(saveXform, start); } if (dragEdge.ToNode == null) { end = Matrix3x2F.TransformPoint(saveXform, end); } m_editor.CircuitRenderer.DrawPartialEdge( dragEdge.FromNode, dragEdge.FromRoute, dragEdge.ToNode, dragEdge.ToRoute, dragEdge.Label, start, end, d2dControl.D2dGraphics ); } else { m_activeEdgeEditor = null; } var csz = d2dControl.ClientSize; d2dControl.D2dGraphics.Transform = Matrix3x2F.Identity; var currentCursor = Cursor.Current; var rect = new Rectangle(); rect.Location = new Point(csz.Width / 2 - currentCursor.HotSpot.X, csz.Height / 2 - currentCursor.HotSpot.Y); rect.Size = Cursor.Current.Size; d2dControl.D2dGraphics.BeginGdiSection(); Graphics g = d2dControl.D2dGraphics.Graphics; Cursor.Current.Draw(g, rect); d2dControl.D2dGraphics.EndGdiSection(); d2dControl.D2dGraphics.Transform = saveXform; } }
/// <summary> /// Performs hit test for a point, in client coordinates</summary> /// <param name="nodes">Nodes to test if hit</param> /// <param name="edges">Edges to test if hit</param> /// <param name="pickPoint">Pick point, in client coordinates</param> /// <returns>Hit record for a point, in client coordinates</returns> public GraphHitRecord <TNode, TEdge, TEdgeRoute> Pick(IEnumerable <TNode> nodes, IEnumerable <TEdge> edges, Point pickPoint) { Matrix3x2F invXform = Matrix3x2F.Invert(m_d2dGraphics.Transform); PointF pt = Matrix3x2F.TransformPoint(invXform, pickPoint); TEdge priorityEdge = null; if (m_selectionContext != null) { priorityEdge = m_selectionContext.GetLastSelected <TEdge>(); } return(m_renderer.Pick(nodes, edges, priorityEdge, pt, m_d2dGraphics)); }
/// <summary> /// Performs hit test for a point, in client coordinates</summary> /// <param name="pickPoint">Pick point, in client coordinates</param> /// <returns>Hit record for a point, in client coordinates</returns> DiagramHitRecord IPickingAdapter2.Pick(Point pickPoint) { Matrix3x2F invXform = Matrix3x2F.Invert(m_d2dGraphics.Transform); PointF pt = Matrix3x2F.TransformPoint(invXform, pickPoint); TEdge priorityEdge = null; if (m_selectionContext != null) { priorityEdge = m_selectionContext.GetLastSelected <TEdge>(); } return(m_renderer.Pick(m_graph, priorityEdge, pt, m_d2dGraphics)); }
/// <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 (in client coords), if either is null</param> /// <param name="g">Graphics object</param> public override void Draw( TNode fromNode, NumberedRoute fromRoute, TNode toNode, NumberedRoute toRoute, string label, Point endPoint, D2dGraphics g) { var inverse = g.Transform; inverse.Invert(); PointF end = Matrix3x2F.TransformPoint(inverse, endPoint); TNode node = (fromNode != null) ? fromNode : toNode; CircleF boundary = GetBoundary(node); Vec2F proj = new Vec2F(); if (CircleF.Project(new Vec2F(end), boundary, ref proj)) { PointF start = new PointF(proj.X, proj.Y); g.DrawLine(start, end, m_theme.OutlineBrush); if (fromNode == null) { PointF temp = end; end = start; start = temp; } Vec2F endTangent = new Vec2F(end.X - start.X, end.Y - start.Y); Vec2F arrowPosition = new Vec2F(end); DrawArrow(arrowPosition, endTangent, m_theme.OutlineBrush, g); if (!string.IsNullOrEmpty(label)) { PointF textPoint = new PointF((end.X + start.X) * 0.5f, (end.Y + start.Y) * 0.5f); RectangleF textBox = new RectangleF(textPoint.X - 512, textPoint.Y, 1024, m_theme.TextFormat.FontHeight); //g.DrawString(label, m_theme.Font, m_theme.TextBrush, textBox, m_theme.CenterStringFormat); g.DrawText(label, m_theme.TextFormat, textBox, m_theme.TextBrush); } } }
private void PaintD2d(object sender, EventArgs e) { if (!IsContextValid()) { return; } var control = (D2dAdaptableControl)AdaptedControl; var sourceControl = m_birdEyeView.m_sourceControl; var srcXformAdapter = sourceControl.Cast <ITransformAdapter>(); D2dGraphics g = control.D2dGraphics; Matrix3x2F invXform = g.Transform; float scaleX = invXform.M11; invXform.Invert(); Point cpt = control.PointToClient(Control.MousePosition); var gpt = Matrix3x2F.TransformPoint(invXform, cpt); // transform client rect of source control to graph space. var srcInvXform = Matrix3x2F.Invert(srcXformAdapter.Transform); var grect = Matrix3x2F.Transform(srcInvXform, sourceControl.ClientRectangle); float strokeWidth = m_dragging || (grect.Contains(gpt) && control.Focused) ? 3.0f / scaleX : 1.5f / scaleX; g.DrawRectangle(grect, Color.Yellow, strokeWidth); Point srcCpt = sourceControl.PointToClient(Control.MousePosition); var srcGpt = Matrix3x2F.TransformPoint(srcInvXform, srcCpt); if (sourceControl.Focused && grect.Contains(srcGpt) && !control.ClientRectangle.Contains(cpt)) { float cursorSize = 7.0f / scaleX; RectangleF cursorRect = new RectangleF(srcGpt.X - cursorSize / 2, srcGpt.Y - cursorSize / 2, cursorSize, cursorSize); g.FillEllipse(cursorRect, Color.Yellow); } }
protected override void OnDragging(MouseEventArgs e) { base.OnDragging(e); if (e.Button != MouseButtons.Left || !IsContextValid()) { return; } AdaptedControl.Capture = true; m_dragging = true; var sourceControl = m_birdEyeView.m_sourceControl; var srcXformAdapter = sourceControl.Cast <ITransformAdapter>(); var inxXform = Matrix3x2F.Invert(m_transformAdapter.Transform); var gpt = Matrix3x2F.TransformPoint(inxXform, e.Location); gpt.X -= m_hitGpt.X; gpt.Y -= m_hitGpt.Y; var srcScale = srcXformAdapter.Scale; srcXformAdapter.Translation = new PointF(-gpt.X * srcScale.X, -gpt.Y * srcScale.Y); }
/// <summary> /// Get currently dragging edge or null /// if currently no edige is being dragged.</summary> /// <returns></returns> public DragEdge GetDraggingEdge() { if (!m_isConnecting) { return(null); } var d2dControl = this.AdaptedControl as D2dAdaptableControl; D2dGraphics gfx = d2dControl.D2dGraphics; var invXform = Matrix3x2F.Invert(gfx.Transform); var edge = new DragEdge(); edge.FromNode = m_draggingContext.ActualFromNode(); edge.FromRoute = m_draggingContext.ActualFromRoute(edge.FromNode); edge.ToNode = m_draggingContext.ActualToNode(); edge.ToRoute = m_draggingContext.ActualToRoute(edge.ToNode); edge.Label = m_draggingContext.ExistingEdge != null ? m_draggingContext.ExistingEdge.Label : null; edge.StartPoint = edge.FromRoute == null?Matrix3x2F.TransformPoint(invXform, m_edgeDragPoint) : m_draggingContext.FromRoutePos; edge.EndPoint = edge.ToRoute == null?Matrix3x2F.TransformPoint(invXform, m_edgeDragPoint) : m_draggingContext.ToRoutePos; return(edge); }
/// <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 in graph space</param> /// <param name="g">D2dGraphics object</param> /// <returns>Hit record containing node and/or edge hit by the given point</returns> public override GraphHitRecord <TNode, TEdge, NumberedRoute> Pick( IGraph <TNode, TEdge, NumberedRoute> graph, TEdge priorityEdge, PointF p, D2dGraphics g) { TNode pickedNode = null; TEdge pickedEdge = null; NumberedRoute fromRoute = null; NumberedRoute 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 node in graph.Nodes.Reverse()) { if (Pick(node, p)) { pickedNode = node; CircleF boundary = GetBoundary(node); boundary.Radius -= m_theme.PickTolerance; bool onEdge = !boundary.Contains(v); if (pickedEdge == null) { if (onEdge) { // edge of node can be source or destination fromRoute = new NumberedRoute(); toRoute = new NumberedRoute(); } } else // hit on edge and node { if (onEdge) { if (pickedEdge.FromNode == pickedNode) { fromRoute = new NumberedRoute(); } else if (pickedEdge.ToNode == pickedNode) { toRoute = new NumberedRoute(); } } } break; } } var result = new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedNode, pickedEdge, fromRoute, toRoute); PointF clientP = Matrix3x2F.TransformPoint(g.Transform, p); if (fromRoute != null) { result.FromRoutePos = clientP; } if (toRoute != null) { result.ToRoutePos = clientP; } if (pickedNode != null && pickedEdge == null) { // label is centered in entire node RectangleF labelBounds = GetBounds(pickedNode, g); float dHeight = labelBounds.Height - m_theme.TextFormat.FontHeight; labelBounds = new RectangleF( labelBounds.X, labelBounds.Y + dHeight / 2, labelBounds.Width, labelBounds.Height - dHeight); if (labelBounds.Contains(p)) { DiagramLabel label = new DiagramLabel( Rectangle.Truncate(labelBounds), TextFormatFlags.SingleLine | TextFormatFlags.HorizontalCenter); return (new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedNode, label)); } } else if (pickedEdge != null) { RectangleF labelBounds = GetLabelBounds(pickedEdge, g); DiagramLabel label = new DiagramLabel( Rectangle.Truncate(labelBounds), TextFormatFlags.SingleLine | TextFormatFlags.HorizontalCenter); if (labelBounds.Contains(p)) { return (new GraphHitRecord <TNode, TEdge, NumberedRoute>(pickedEdge, label)); } } return(result); }
/// <summary> /// Transforms point by inverse transform</summary> /// <param name="matrix">Matrix representing transform</param> /// <param name="p">Point</param> /// <returns>Inverse transformed point</returns> public static Point InverseTransform(Matrix3x2F matrix, Point p) { Matrix3x2F inverse = Matrix3x2F.Invert(matrix); return(Point.Truncate(Matrix3x2F.TransformPoint(inverse, p))); }