Ejemplo n.º 1
0
        // All label-vertexes are assigned the same vertical size independently of text descenders etc.
        private Dictionary <Vertex, SKSize> ComputeUniformVertexSizes(IEnumerable <Vertex> vertexes, float textHeight, float padding)
        {
            SKRect fitRect = MeasureVertexText(vertexes, textHeight);
            Dictionary <Vertex, SKSize> vertexSizes = new Dictionary <Vertex, SKSize>();

            using (var paint = new SKPaint()) {
                paint.TextSize = textHeight; paint.IsAntialias = true; paint.Color = SKColors.Black; paint.IsStroke = false;
                var bounds = new SKRect();
                foreach (Vertex v in vertexes)
                {
                    if (v is Vertex_Label)
                    {
                        float width = GraphLayout.PaintMeasureText(paint, (v as Vertex_Label).Label, ref bounds);
                        vertexSizes[v] = new SKSize(
                            width + 2 * padding, // use width, not (bounds.Right - bounds.Left)
                            (fitRect.Bottom - fitRect.Top) + 2 * padding);
                    }
                    else if (v is Vertex_Rectangle)
                    {
                        SKSize size = (v as Vertex_Rectangle).Size;
                        vertexSizes[v] = new SKSize(textHeight * size.Width, textHeight * size.Height);
                    }
                    else if (v is Vertex_Routing)
                    {
                        vertexSizes[v] = new SKSize(0, 0);
                    }
                }
            }
            return(vertexSizes);
        }
Ejemplo n.º 2
0
        // Get the bounding rect of the text found in all the vertices (used mostly for bounding hight)
        private SKRect MeasureVertexText(IEnumerable <Vertex> vertexes, float textHeight)
        {
            SKRect fitRect = new SKRect(0, 0, 0, 0);

            using (var paint = new SKPaint()) {
                paint.TextSize = textHeight; paint.IsAntialias = true; paint.Color = SKColors.Black; paint.IsStroke = false;
                var bounds = new SKRect();
                foreach (Vertex v in vertexes)
                {
                    if (v is Vertex_Label)
                    {
                        float width = GraphLayout.PaintMeasureText(paint, (v as Vertex_Label).Label, ref bounds);
                        fitRect.Left   = Math.Min(fitRect.Left, bounds.Left);
                        fitRect.Top    = Math.Min(fitRect.Top, bounds.Top);
                        fitRect.Right  = Math.Max(fitRect.Right, bounds.Right);
                        fitRect.Bottom = Math.Max(fitRect.Bottom, bounds.Bottom);
                    }
                }
            }
            return(fitRect);
        }
Ejemplo n.º 3
0
        public GraphLayoutView()
        {
            // register this as KTouchable so that touch callbacks can be attached through interface KTouchable:
            // (If we want to add special actions for Tap, etc. beyond built-in two-finger swiping and zooming)
            // KGraphHandler.Register(this); // this as KTouchable

            this.BackgroundColor = Color.Transparent;
            this.PaintSurface   += OnPaintCanvas;

            /* Attact Touch effect from KTouch.OnTouchEffectAction */
            TouchEffect touchEffect = new TouchEffect();

            touchEffect.TouchAction += KTouchServer.OnTouchEffectAction;
            touchEffect.Capture      = true; // "This has the effect of delivering all subsequent events to the same event handler"
            this.Effects.Add(touchEffect);

            /* Initialize Interface KTouchClient with a locally-sourced KTouchClientData closure */
            this.data = new KTouchClientData(
                invalidateSurface: () => { this.InvalidateSurface(); },
                setManualPinchPan: (Swipe pinchPan) => { GraphLayout.SetManualPinchPan(pinchPan); }
                );
        }
Ejemplo n.º 4
0
        private void DrawSplineEdge(SKCanvas canvas, Kaemika.Edge <Vertex> edge, float nodeHeight, float textSize, SKColor color, Swipe swipe)
        {
            if (edge.Source is Vertex_Routing)
            {
                return;                                // this edge it will be drawn as part of another edge
            }
            List <SKPoint> edgePath = new List <SKPoint>();

            Kaemika.Edge <Vertex> routedEdge = edge;
            (SKPoint firstSource, SKPoint firstTarget) = AddEdgePath(edgePath, routedEdge);
            while (routedEdge.Target is Vertex_Routing)
            {
                routedEdge = (routedEdge.Target as Vertex_Routing).toEdge;
                AddEdgePath(edgePath, routedEdge);
            }
            edgePath.Insert(0, edgePath[0]); // duplicate first point for spline
            SKPoint ultimate    = edgePath[edgePath.Count - 1];
            SKPoint penultimate = edgePath[edgePath.Count - 2];

            edgePath.Insert(edgePath.Count, ultimate); // duplicate last point for spline
            List <SKPoint> controlPoints = ControlPoints(edgePath);
            SKPath         path          = AddBeziers(new SKPath(), controlPoints.ToArray(), swipe);

            using (var paint = new SKPaint()) {
                paint.TextSize = 10.0f; paint.IsAntialias = true; paint.Color = color; paint.IsStroke = true;
                canvas.DrawPath(path, paint);

                SKPoint arrowHeadBase = ultimate;
                if (routedEdge.Directed != Directed.No)   // draw arrowhead on last routedEdge segment, update arrowHeadBase
                {
                    VectorStd lineVector = VectorStd.DifferenceVector(ultimate, penultimate);
                    float     lineLength = lineVector.Length;
                    // calculate point at base of arrowhead
                    float     arrowWidth         = nodeHeight / 6;
                    float     tPointOnLine       = (float)(arrowWidth / (2 * (Math.Tan(120) / 2) * lineLength));
                    VectorStd arrowReverseVector = -tPointOnLine * lineVector;
                    arrowHeadBase = ultimate + arrowReverseVector;
                    SKPoint   arrowHeadMid = ultimate + (0.5F * arrowReverseVector);
                    VectorStd normalVector = new VectorStd(-lineVector.Y, lineVector.X);
                    float     tNormal      = arrowWidth / (2 * lineLength);
                    SKPoint   leftPoint    = arrowHeadBase + tNormal * normalVector;
                    SKPoint   rightPoint   = arrowHeadBase + -tNormal * normalVector;
                    if (routedEdge.Directed == Directed.Solid)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % ultimate);
                        arrowPath.LineTo(swipe % rightPoint); arrowPath.Close();
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (routedEdge.Directed == Directed.Pointy)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = true;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % ultimate);
                        arrowPath.LineTo(swipe % rightPoint);
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (routedEdge.Directed == Directed.Ball)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        canvas.DrawCircle(swipe % arrowHeadMid, swipe % (arrowReverseVector.Length / 2), paint);
                    }
                }
                // if (routedEdge.Directed == Directed.Solid) { paint.IsStroke = false; canvas.DrawCircle(path.LastPoint, 20, paint); }
                // if (routedEdge.Directed == Directed.Pointy) { paint.IsStroke = true; canvas.DrawCircle(path.LastPoint, 20, paint); }

                if (edge.Label != null)   // draw label on first routedEdge segment
                {
                    var saveTextSize = paint.TextSize;
                    paint.TextSize = swipe % textSize / 3;
                    SKPoint labelTarget = (firstTarget == ultimate) ? arrowHeadBase : firstTarget;
                    GraphLayout.CanvasDrawTextCentered(canvas, edge.Label, swipe % new SKPoint((firstSource.X + labelTarget.X) / 2, (firstSource.Y + labelTarget.Y) / 2), paint, true);
                    paint.TextSize = saveTextSize;
                }
            }
        }
Ejemplo n.º 5
0
        private void DrawEdge(SKCanvas canvas, Kaemika.Edge <Vertex> edge, float nodeHeight, float textSize, SKColor color, Swipe swipe)
        {
            bool spline = false; bool arc = false;

            using (var paint = new SKPaint()) {
                paint.TextSize = 10.0f; paint.IsAntialias = true; paint.Color = color;

                SKPoint source     = layoutInfo.vertexPositions[edge.Source];
                SKPoint target     = layoutInfo.vertexPositions[edge.Target];
                SKSize  sourceSize = layoutInfo.vertexSizes[edge.Source];
                SKSize  targetSize = layoutInfo.vertexSizes[edge.Target];

                if (layoutInfo.edgeRoutes == null)
                {
                    layoutInfo.edgeRoutes = new Dictionary <Kaemika.Edge <Vertex>, SKPoint[]>();
                }
                SKPoint[] route = (layoutInfo.edgeRoutes.ContainsKey(edge)) ? layoutInfo.edgeRoutes[edge] : new SKPoint[] { };

                var     routePath     = new SKPath(); paint.IsStroke = true;
                SKPoint initialTarget = (route.Length == 0) ? target : route[0];
                SKPoint firstSource   = PointOnRectangle(source, initialTarget, sourceSize.Width / 2, sourceSize.Height / 2);
                routePath.MoveTo(swipe % firstSource);
                SKPoint lastSource = firstSource;
                foreach (var nextTarget in route)
                {
                    if (spline)
                    {
                        (SKPoint control, SKPoint nextControl) = SplineControls(lastSource, nextTarget, new SKSize(textSize, textSize));
                        routePath.CubicTo(swipe % control, swipe % nextControl, swipe % nextTarget);
                    }
                    else
                    {
                        routePath.LineTo(swipe % nextTarget);
                    }
                    lastSource = nextTarget;
                }
                SKPoint lastTarget  = PointOnRectangle(target, lastSource, targetSize.Width / 2, targetSize.Height / 2);
                SKPoint firstTarget = (route.Length == 0) ? lastTarget : initialTarget;
                if (spline)
                {
                    (SKPoint control, SKPoint nextControl) = SplineControls(lastSource, lastTarget, new SKSize(textSize, textSize));
                    routePath.CubicTo(swipe % control, swipe % nextControl, swipe % lastTarget);
                }
                else if (arc && route.Length == 0)
                {
                    routePath.ArcTo(swipe % lastSource, swipe % lastTarget, swipe % textSize);                                // see Postscript arct
                }
                else
                {
                    routePath.LineTo(swipe % lastTarget);
                }
                canvas.DrawPath(routePath, paint);

                SKPoint arrowHeadBase = lastTarget;

                //SKPoint nextSource = source;
                //foreach (var nextTarget in route) {
                //    if (nextSource == source) nextSource = PointOnRectangle(source, nextTarget, sourceSize.Width / 2, sourceSize.Height / 2);
                //    canvas.DrawLine(swipe % nextSource, swipe % nextTarget, paint);
                //    nextSource = nextTarget;
                //}
                //SKPoint lastSource = (nextSource != source) ? nextSource : PointOnRectangle(source, target, sourceSize.Width / 2, sourceSize.Height / 2);
                //SKPoint lastTarget = PointOnRectangle(target, lastSource, targetSize.Width / 2, targetSize.Height / 2);
                //canvas.DrawLine(swipe % lastSource, swipe % lastTarget, paint);

                //SKPoint pointOnLine = lastTarget;

                if (edge.Directed != Directed.No)   // draw arrowhead, update arrowHeadBase
                {
                    VectorStd lineVector = VectorStd.DifferenceVector(lastTarget, lastSource);
                    float     lineLength = lineVector.Length;
                    // calculate point at base of arrowhead
                    float arrowWidth   = nodeHeight / 6;
                    float tPointOnLine = (float)(arrowWidth / (2 * (Math.Tan(120) / 2) * lineLength));
                    arrowHeadBase = lastTarget + (-tPointOnLine * lineVector);
                    VectorStd normalVector = new VectorStd(-lineVector.Y, lineVector.X);
                    float     tNormal      = arrowWidth / (2 * lineLength);
                    SKPoint   leftPoint    = arrowHeadBase + tNormal * normalVector;
                    SKPoint   rightPoint   = arrowHeadBase + -tNormal * normalVector;
                    if (edge.Directed == Directed.Solid)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = false;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % lastTarget);
                        arrowPath.LineTo(swipe % rightPoint); arrowPath.Close();
                        canvas.DrawPath(arrowPath, paint);
                    }
                    if (edge.Directed == Directed.Pointy)
                    {
                        var arrowPath = new SKPath(); paint.IsStroke = true;
                        arrowPath.MoveTo(swipe % leftPoint); arrowPath.LineTo(swipe % lastTarget);
                        arrowPath.LineTo(swipe % rightPoint);
                        canvas.DrawPath(arrowPath, paint);
                    }
                }

                if (edge.Label != null)   // draw label
                {
                    var saveTextSize = paint.TextSize;
                    paint.TextSize = swipe % textSize / 3;
                    SKPoint labelTarget = (route.Length == 0) ? arrowHeadBase : firstTarget;
                    GraphLayout.CanvasDrawTextCentered(canvas, edge.Label, swipe % new SKPoint((firstSource.X + labelTarget.X) / 2, (firstSource.Y + labelTarget.Y) / 2), paint, true);
                    paint.TextSize = saveTextSize;
                    //var path = new SKPath(); paint.IsStroke = false;
                    //path.MoveTo(swipe % firstSource);
                    //path.LineTo(swipe % ((route.Length == 0) ? arrowHeadBase : firstTarget));
                    //path.Close(); // so the text wraps back around the closed single-line path
                    //paint.TextSize = swipe % textSize / 3;
                    //canvas.DrawTextOnPath(edge.Label, path, new SKPoint(paint.TextSize/2, -paint.TextSize/2), paint);
                }
            }
        }
Ejemplo n.º 6
0
 private SKRect DrawLabel(SKCanvas canvas, string text, SKPoint p, float textSize, SKColor color, Swipe swipe)
 {
     return(GraphLayout.CanvasDrawTextCentered(canvas, text, swipe % p, swipe % textSize, color, false));
 }
Ejemplo n.º 7
0
 public static void SetGraphLayout(GraphLayout layout)
 {
     graphLayout = layout; // caller needs to Invalidate after this
 }