Example #1
0
        DrawCombinedIntergroupEdge
        (
            DrawingContext oDrawingContext,
            GraphDrawingContext oGraphDrawingContext,
            IntergroupEdgeInfo oCombinedIntergroupEdge,
            GroupLayoutDrawingInfo oGroupLayoutDrawingInfo
        )
        {
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(oCombinedIntergroupEdge != null);
            Debug.Assert(oGroupLayoutDrawingInfo != null);
            AssertValid();

            Rect oGroupRectangle1, oGroupRectangle2;

            if (
                !TryGetGroupRectangle(

                    oGroupLayoutDrawingInfo.GroupsToDraw[
                        oCombinedIntergroupEdge.Group1Index],

                    out oGroupRectangle1)
                ||
                !TryGetGroupRectangle(

                    oGroupLayoutDrawingInfo.GroupsToDraw[
                        oCombinedIntergroupEdge.Group2Index],

                    out oGroupRectangle2)
                )
            {
                return;
            }

            Point oGroupRectangle1Center =
                WpfGraphicsUtil.GetRectCenter(oGroupRectangle1);

            Point oGroupRectangle2Center =
                WpfGraphicsUtil.GetRectCenter(oGroupRectangle2);

            Point oBezierControlPoint = GetBezierControlPoint(oGraphDrawingContext,
                                                              oGroupRectangle1Center, oGroupRectangle2Center,
                                                              CombinedIntergroupEdgeBezierDisplacementFactor
                                                              );

            PathGeometry oBezierCurve =
                WpfPathGeometryUtil.GetQuadraticBezierCurve(oGroupRectangle1Center,
                                                            oGroupRectangle2Center, oBezierControlPoint);

            Color oColor = GetContrastingColor(
                oGraphDrawingContext, CombinedIntergroupEdgeAlpha, true);

            Pen oPen = CreateFrozenPen(CreateFrozenSolidColorBrush(oColor),

                                       GetCombinedIntergroupEdgePenWidth(oCombinedIntergroupEdge) *
                                       this.GraphScale,

                                       DashStyles.Solid, PenLineCap.Round);

            oDrawingContext.DrawGeometry(null, oPen, oBezierCurve);
        }
        SaveObject
        (
            Object oObject,
            String sFileName
        )
        {
            Debug.Assert(oObject is GraphImageInfo);
            Debug.Assert(!String.IsNullOrEmpty(sFileName));

            GraphImageInfo oGraphImageInfo = (GraphImageInfo)oObject;
            Int32          iWidth          = oGraphImageInfo.Width;
            Int32          iHeight         = oGraphImageInfo.Height;

            GraphImageCompositor oGraphImageCompositor =
                new GraphImageCompositor(oGraphImageInfo.NodeXLControl);

            UIElement oCompositeElement = null;

            try
            {
                if (m_oSaveFileDialog.FilterIndex <=
                    SaveableImageFormats.ImageFormats.Length)
                {
                    // The graph must be saved as a bitmap.

                    oCompositeElement = oGraphImageCompositor.Composite(
                        iWidth, iHeight, oGraphImageInfo.HeaderText,
                        oGraphImageInfo.FooterText,
                        oGraphImageInfo.HeaderFooterFont,
                        oGraphImageInfo.LegendControls);

                    System.Drawing.Bitmap oBitmap = WpfGraphicsUtil.VisualToBitmap(
                        oCompositeElement, iWidth, iHeight);

                    base.SaveObject(oBitmap, sFileName);
                    oBitmap.Dispose();
                }
                else
                {
                    // The graph must be saved as an XPS.

                    Double documentWidth  = ToWpsUnits(iWidth);
                    Double documentHeight = ToWpsUnits(iHeight);

                    oCompositeElement = oGraphImageCompositor.Composite(
                        documentWidth, documentHeight, oGraphImageInfo.HeaderText,
                        oGraphImageInfo.FooterText,
                        oGraphImageInfo.HeaderFooterFont,
                        oGraphImageInfo.LegendControls);

                    Size oDocumentSize      = new Size(documentWidth, documentHeight);
                    Rect oDocumentRectangle = new Rect(new Point(), oDocumentSize);

                    FixedDocument oFixedDocument = new FixedDocument();
                    oFixedDocument.DocumentPaginator.PageSize = oDocumentSize;
                    PageContent oPageContent = new PageContent();

                    FixedPage oFixedPage = new FixedPage();
                    oFixedPage.Width  = documentWidth;
                    oFixedPage.Height = documentHeight;

                    oFixedPage.Children.Add(oCompositeElement);

                    ((System.Windows.Markup.IAddChild)oPageContent).AddChild(
                        oFixedPage);

                    oFixedDocument.Pages.Add(oPageContent);

                    XpsDocument oXpsDocument = new XpsDocument(sFileName,
                                                               FileAccess.Write);

                    XpsDocumentWriter oXpsDocumentWriter =
                        XpsDocument.CreateXpsDocumentWriter(oXpsDocument);

                    oXpsDocumentWriter.Write(oFixedDocument);
                    oXpsDocument.Close();
                }
            }
            finally
            {
                if (oCompositeElement != null)
                {
                    oGraphImageCompositor.RestoreNodeXLControl();
                }
            }
        }
        TransferToGraphDrawer
        (
            GraphDrawer graphDrawer
        )
        {
            Debug.Assert(graphDrawer != null);
            AssertValid();

            this.LabelUserSettings.TransferToGraphDrawer(graphDrawer);

            graphDrawer.BackColor =
                WpfGraphicsUtil.ColorToWpfColor(this.BackColor);

            if (!String.IsNullOrEmpty(this.BackgroundImageUri))
            {
                graphDrawer.BackgroundImage =
                    (new WpfImageUtil()).GetImageSynchronousIgnoreDpi(
                        this.BackgroundImageUri);
            }
            else
            {
                graphDrawer.BackgroundImage = null;
            }

            EdgeDrawer   oEdgeDrawer   = graphDrawer.EdgeDrawer;
            VertexDrawer oVertexDrawer = graphDrawer.VertexDrawer;

            EdgeWidthConverter oEdgeWidthConverter = new EdgeWidthConverter();
            AlphaConverter     oAlphaConverter     = new AlphaConverter();

            oEdgeDrawer.Width =
                oEdgeWidthConverter.WorkbookToGraph(this.EdgeWidth);

            oEdgeDrawer.Color = WpfGraphicsUtil.ColorToWpfColor(

                Color.FromArgb(oAlphaConverter.WorkbookToGraphAsByte(
                                   this.EdgeAlpha),

                               this.EdgeColor)
                );

            oEdgeDrawer.CurveStyle = this.EdgeCurveStyle;

            oEdgeDrawer.BezierDisplacementFactor =
                this.EdgeBezierDisplacementFactor;

            oEdgeDrawer.SelectedColor = WpfGraphicsUtil.ColorToWpfColor(
                this.SelectedEdgeColor);

            oEdgeDrawer.RelativeArrowSize = this.RelativeArrowSize;

            oVertexDrawer.Shape = this.VertexShape;

            oVertexDrawer.Radius = (new VertexRadiusConverter()).WorkbookToGraph(
                this.VertexRadius);

            oVertexDrawer.Effect = this.VertexEffect;
            oVertexDrawer.RelativeOuterGlowSize = this.VertexRelativeOuterGlowSize;

            oVertexDrawer.Color = WpfGraphicsUtil.ColorToWpfColor(

                Color.FromArgb(oAlphaConverter.WorkbookToGraphAsByte(
                                   this.VertexAlpha),

                               this.VertexColor)
                );

            oVertexDrawer.SelectedColor = WpfGraphicsUtil.ColorToWpfColor(
                this.SelectedVertexColor);
        }
        GetEdgeEndpointOnRectangle
        (
            Point oVertexALocation,
            Rect oVertexARectangle,
            Point oVertexBLocation,
            out Point oEdgeEndpoint
        )
        {
            AssertValid();

            if (oVertexALocation == oVertexBLocation)
            {
                oEdgeEndpoint = oVertexALocation;

                return;
            }

            Double dVertexAX = oVertexALocation.X;
            Double dVertexAY = oVertexALocation.Y;

            Double dVertexBX = oVertexBLocation.X;
            Double dVertexBY = oVertexBLocation.Y;

            Double dHalfVertexARectangleWidth  = oVertexARectangle.Width / 2.0;
            Double dHalfVertexARectangleHeight = oVertexARectangle.Height / 2.0;

            // Get the angle between vertex A and vertex B.

            Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPointsRadians(
                oVertexALocation, oVertexBLocation);

            // Get the angle that defines the aspect ratio of vertex A's rectangle.

            Double dAspectAngle = Math.Atan2(
                dHalfVertexARectangleHeight, dHalfVertexARectangleWidth);

            if (dEdgeAngle >= -dAspectAngle && dEdgeAngle < dAspectAngle)
            {
                // For a square, this is -45 degrees to 45 degrees.

                Debug.Assert(dVertexBX != dVertexAX);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleWidth,

                    dVertexAY + dHalfVertexARectangleWidth *
                    ((dVertexBY - dVertexAY) / (dVertexBX - dVertexAX))
                    );

                return;
            }

            if (dEdgeAngle >= dAspectAngle && dEdgeAngle < Math.PI - dAspectAngle)
            {
                // For a square, this is 45 degrees to 135 degrees.

                Debug.Assert(dVertexBY != dVertexAY);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleHeight *
                    ((dVertexBX - dVertexAX) / (dVertexAY - dVertexBY)),

                    dVertexAY - dHalfVertexARectangleHeight
                    );

                return;
            }

            if (dEdgeAngle < -dAspectAngle && dEdgeAngle >= -Math.PI + dAspectAngle)
            {
                // For a square, this is -45 degrees to -135 degrees.

                Debug.Assert(dVertexBY != dVertexAY);

                oEdgeEndpoint = new Point(

                    dVertexAX + dHalfVertexARectangleHeight *
                    ((dVertexBX - dVertexAX) / (dVertexBY - dVertexAY)),

                    dVertexAY + dHalfVertexARectangleHeight
                    );

                return;
            }

            // For a square, this is 135 degrees to 180 degrees and -135 degrees to
            // -180 degrees.

            Debug.Assert(dVertexAX != dVertexBX);

            oEdgeEndpoint = new Point(

                dVertexAX - dHalfVertexARectangleWidth,

                dVertexAY + dHalfVertexARectangleWidth *
                ((dVertexBY - dVertexAY) / (dVertexAX - dVertexBX))
                );
        }
Example #5
0
        GetBezierControlPoint
        (
            GraphDrawingContext oGraphDrawingContext,
            Point oEndpoint1,
            Point oEndpoint2,
            Double dBezierDisplacementFactor
        )
        {
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(dBezierDisplacementFactor >= 0);
            AssertValid();

            // This method finds the midpoint of the straight line between the two
            // endpoints, then calculates a point that is displaced from the
            // midpoint at a right angle.  This is analagous to pulling a taut
            // string at its midpoint.
            //
            // The calculations are based on the anonymous post "How Can I
            // Calculate The Cartesian Coordinates Of A The Third Corner Of A
            // Triangle If I Have The Lengths Of All Three Sides And The
            // Coordinates Of The First Two Corners?" at
            // http://www.blurtit.com/q9044151.html.

            // Point a, the first endpoint, is one vertex of a right triangle.

            Double dPointAX = oEndpoint1.X;
            Double dPointAY = oEndpoint1.Y;

            // Point b, the midpoint of the line between the two endpoints, is
            // another vertex of the right triangle.  The angle at b is 90 degrees.

            Double dPointBX = dPointAX + (oEndpoint2.X - dPointAX) / 2.0;
            Double dPointBY = dPointAY + (oEndpoint2.Y - dPointAY) / 2.0;

            // Side C connects points a and b.

            Double dSideCLength = WpfGraphicsUtil.GetDistanceBetweenPoints(
                new Point(dPointBX, dPointBY), oEndpoint1);

            // Side A connects points b and c, where c is the point we need to
            // calculate.  Make the length of A, which is the displacement
            // mentioned above, proportional to the length of the line between the
            // two endpoints, so that a longer line gets displaced more than a
            // shorter line.

            Double dSideALength = dSideCLength * dBezierDisplacementFactor;

            // Calculate the angle of the line between the two endpoints.

            Double dAbsAtan2 = Math.Abs(Math.Atan2(
                                            Math.Max(oEndpoint2.Y, dPointAY) - Math.Min(oEndpoint2.Y, dPointAY),
                                            Math.Max(oEndpoint2.X, dPointAX) - Math.Min(oEndpoint2.X, dPointAX)
                                            ));

            Rect oGraphRectangle = oGraphDrawingContext.GraphRectangle;

            if (dAbsAtan2 >= Math.PI / 4.0 && dAbsAtan2 <= 3.0 * Math.PI / 4.0)
            {
                // The line between the two endpoints is closer to vertical than
                // horizontal.
                //
                // As explained in the post mentioned above, the length of side A
                // can be negative or positive, depending on which direction point
                // c should be displaced.  The following adjustments to
                // dSideALength were determined experimentally.

                if (oEndpoint2.Y > dPointAY)
                {
                    dSideALength *= -1.0;
                }

                if (dPointBX - oGraphRectangle.Left <
                    oGraphRectangle.Right - dPointBX)
                {
                    dSideALength *= -1.0;
                }
            }
            else
            {
                // The line between the two endpoints is closer to horizontal than
                // vertical.

                if (oEndpoint2.X < dPointAX)
                {
                    dSideALength *= -1.0;
                }

                if (dPointBY - oGraphRectangle.Top <
                    oGraphRectangle.Bottom - dPointBY)
                {
                    dSideALength *= -1.0;
                }
            }

            // Calculate point c.

            Double dPointCX = dPointBX +
                              (dSideALength * (dPointAY - dPointBY)) / dSideCLength;

            Double dPointCY = dPointBY +
                              (dSideALength * (dPointBX - dPointAX)) / dSideCLength;

            // Don't let point c fall outside the graph's margins.

            return(WpfGraphicsUtil.MovePointWithinBounds(
                       new Point(dPointCX, dPointCY),
                       oGraphDrawingContext.GraphRectangleMinusMargin));
        }
Example #6
0
        DrawArrow
        (
            DrawingContext oDrawingContext,
            Point oArrowTipLocation,
            Double dArrowAngle,
            Color oColor,
            Double dEdgeWidth
        )
        {
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(dEdgeWidth > 0);
            AssertValid();

            // Compute the arrow's dimensions.  The width factor is arbitrary and
            // was determined experimentally.

            const Double WidthFactor = 1.5;

            Double dArrowTipX       = oArrowTipLocation.X;
            Double dArrowTipY       = oArrowTipLocation.Y;
            Double dArrowWidth      = WidthFactor * dEdgeWidth * m_dRelativeArrowSize;
            Double dArrowHalfHeight = dArrowWidth / 2.0;
            Double dX = dArrowTipX - dArrowWidth;

            // Compute the arrow's three points as if the arrow were at an angle of
            // zero degrees, then use a rotated transform to adjust for the actual
            // specified angle.

            Point [] aoPoints = new Point [] {
                // Index 0: Arrow tip.

                oArrowTipLocation,

                // Index 1: Arrow bottom.

                new Point(dX, dArrowTipY - dArrowHalfHeight),

                // Index 2: Arrow top.

                new Point(dX, dArrowTipY + dArrowHalfHeight),

                // Index 3: Center of the flat end of the arrow.
                //
                // Note: The 0.2 is to avoid a gap between the edge endcap and the
                // flat end of the arrow, but it sometimes causes the two to
                // overlap slightly, and that can show if the edge isn't opaque.
                // What is the correct way to get the endcap to merge invisibly
                // with the arrow?

                new Point(dX + 0.2, dArrowTipY)
            };

            Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oArrowTipLocation,
                                                              -MathUtil.RadiansToDegrees(dArrowAngle));

            oMatrix.Transform(aoPoints);

            PathGeometry oArrow = WpfGraphicsUtil.PathGeometryFromPoints(
                aoPoints[0], aoPoints[1], aoPoints[2]);

            oDrawingContext.DrawGeometry(GetBrush(oColor), null, oArrow);

            return(aoPoints[3]);
        }
Example #7
0
        GetEdgeEndpoint
        (
            Point otherEndpoint,
            out Point edgeEndpoint
        )
        {
            AssertValid();

            Point oVertexLocation = this.VertexLocation;

            // Instead of doing geometry calculations similar to what is done in
            // VertexDrawingHistory.GetEdgePointOnRectangle(), make use of that
            // method by making the triangle look like a rectangle.  First, figure
            // out how to rotate the triangle about the vertex location so that the
            // side containing the endpoint is vertical and to the right of the
            // vertex location.

            Double dEdgeAngle = WpfGraphicsUtil.GetAngleBetweenPointsRadians(
                oVertexLocation, otherEndpoint);

            Double dEdgeAngleDegrees = MathUtil.RadiansToDegrees(dEdgeAngle);

            Double dAngleToRotateDegrees;

            if (dEdgeAngleDegrees >= -30.0 && dEdgeAngleDegrees < 90.0)
            {
                dAngleToRotateDegrees = 30.0;
            }
            else if (dEdgeAngleDegrees >= -150.0 && dEdgeAngleDegrees < -30.0)
            {
                dAngleToRotateDegrees = 270.0;
            }
            else
            {
                dAngleToRotateDegrees = 150.0;
            }

            // Now create a rotated rectangle that is centered on the vertex
            // location and that has the vertical, endpoint-containing triangle
            // side as the rectangle's right edge.

            Double dWidth = 2.0 * m_dHalfWidth;

            Rect oRotatedRectangle = new Rect(
                oVertexLocation.X,
                oVertexLocation.Y - m_dHalfWidth,
                dWidth * WpfGraphicsUtil.Tangent30Degrees,
                dWidth
                );

            Matrix oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation,
                                                              dAngleToRotateDegrees);

            // Rotate the other vertex location.

            Point oRotatedOtherVertexLocation = oMatrix.Transform(otherEndpoint);

            // GetEdgeEndpointOnRectangle will compute an endpoint on the
            // rectangle's right edge.

            Point oRotatedEdgeEndpoint;

            GetEdgeEndpointOnRectangle(oVertexLocation, oRotatedRectangle,
                                       oRotatedOtherVertexLocation, out oRotatedEdgeEndpoint);

            // Now rotate the edge endpoint in the other direction.

            oMatrix = WpfGraphicsUtil.GetRotatedMatrix(oVertexLocation,
                                                       -dAngleToRotateDegrees);

            edgeEndpoint = oMatrix.Transform(oRotatedEdgeEndpoint);
        }
Example #8
0
        GetDashStyle
        (
            IEdge oEdge,
            Double dWidth,
            Boolean bDrawAsSelected
        )
        {
            Debug.Assert(oEdge != null);
            Debug.Assert(dWidth >= 0);
            AssertValid();

            // Note:
            //
            // An early implementation used the predefined DashStyle objects
            // provided by the DashStyles class, but those did not look good at
            // smaller edge widths.  This implementation builds the DashStyle's
            // Dashes collection from scratch.

            Double [] adDashes = null;

            if (!bDrawAsSelected)
            {
                Object oPerEdgeStyleAsObject;

                // Check for a per-edge style.

                if (oEdge.TryGetValue(ReservedMetadataKeys.PerEdgeStyle,
                                      typeof(EdgeStyle), out oPerEdgeStyleAsObject))
                {
                    switch ((EdgeStyle)oPerEdgeStyleAsObject)
                    {
                    case EdgeStyle.Solid:

                        break;

                    case EdgeStyle.Dash:

                        adDashes = new Double[] { 4.0, 2.0 };
                        break;

                    case EdgeStyle.Dot:

                        adDashes = new Double[] { 1.0, 2.0 };
                        break;

                    case EdgeStyle.DashDot:

                        adDashes = new Double[] { 4.0, 2.0, 1.0, 2.0 };
                        break;

                    case EdgeStyle.DashDotDot:

                        adDashes = new Double[] { 4.0, 2.0, 1.0, 2.0, 1.0, 2.0 };
                        break;

                    default:

                        throw new FormatException(String.Format(

                                                      "{0}: The edge with the ID {1} has an invalid {2}"
                                                      + " value."
                                                      ,
                                                      this.ClassName,
                                                      oEdge.ID,
                                                      "ReservedMetadataKeys.PerEdgeStyle"
                                                      ));
                    }
                }
            }

            if (adDashes == null)
            {
                return(DashStyles.Solid);
            }

            DashStyle oDashStyle = new DashStyle();

            oDashStyle.Dashes = new DoubleCollection(adDashes);
            WpfGraphicsUtil.FreezeIfFreezable(oDashStyle);

            return(oDashStyle);
        }
Example #9
0
        TryDrawEdge
        (
            IEdge edge,
            GraphDrawingContext graphDrawingContext,
            out EdgeDrawingHistory edgeDrawingHistory
        )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            edgeDrawingHistory = null;

            // If the edge is hidden, do nothing.

            VisibilityKeyValue eVisibility = GetVisibility(edge);

            if (eVisibility == VisibilityKeyValue.Hidden)
            {
                return(false);
            }

            Boolean   bDrawAsSelected = GetDrawAsSelected(edge);
            Color     oColor          = GetColor(edge, eVisibility, bDrawAsSelected);
            Double    dWidth          = GetWidth(edge, bDrawAsSelected);
            DashStyle oDashStyle      = GetDashStyle(edge, dWidth, bDrawAsSelected);
            Boolean   bDrawArrow      = (m_bDrawArrowOnDirectedEdge && edge.IsDirected);

            IVertex [] aoVertices = edge.Vertices;

            DrawingVisual oDrawingVisual = new DrawingVisual();

            using (DrawingContext oDrawingContext = oDrawingVisual.RenderOpen())
            {
                if (edge.IsSelfLoop)
                {
                    if (!TryDrawSelfLoop(aoVertices[0], oDrawingContext,
                                         graphDrawingContext, oColor, dWidth, bDrawArrow))
                    {
                        // The edge's vertex is hidden, so the edge should be
                        // hidden also.

                        return(false);
                    }
                }
                else
                {
                    Point oEdgeEndpoint1, oEdgeEndpoint2;

                    if (!TryGetEdgeEndpoints(aoVertices[0], aoVertices[1],
                                             graphDrawingContext, out oEdgeEndpoint1,
                                             out oEdgeEndpoint2))
                    {
                        // One of the edge's vertices is hidden, so the edge should
                        // be hidden also.

                        return(false);
                    }

                    if (bDrawArrow)
                    {
                        // Draw the arrow and set the second endpoint to the center
                        // of the flat end of the arrow.

                        Double dArrowAngle = WpfGraphicsUtil.GetAngleBetweenPoints(
                            oEdgeEndpoint1, oEdgeEndpoint2);

                        oEdgeEndpoint2 = DrawArrow(oDrawingContext, oEdgeEndpoint2,
                                                   dArrowAngle, oColor, dWidth);
                    }

                    // Draw the edge.

                    oDrawingContext.DrawLine(GetPen(oColor, dWidth, oDashStyle),
                                             oEdgeEndpoint1, oEdgeEndpoint2);

                    // Draw the edge's label, if there is one.

                    Object oLabelAsObject;

                    if (edge.TryGetValue(ReservedMetadataKeys.PerEdgeLabel,
                                         typeof(String), out oLabelAsObject) &&
                        oLabelAsObject != null)
                    {
                        DrawLabel(oDrawingContext, graphDrawingContext,
                                  oEdgeEndpoint1, oEdgeEndpoint2,
                                  (String)oLabelAsObject, oColor);
                    }
                }

                // Retain information about the edge that was drawn.

                edgeDrawingHistory = new EdgeDrawingHistory(
                    edge, oDrawingVisual, bDrawAsSelected);

                return(true);
            }
        }
Example #10
0
        DrawLabel
        (
            DrawingContext oDrawingContext,
            GraphDrawingContext oGraphDrawingContext,
            Point oEdgeEndpoint1,
            Point oEdgeEndpoint2,
            String sLabel,
            Color oColor
        )
        {
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(sLabel != null);
            AssertValid();

            if (sLabel.Length == 0)
            {
                return;
            }

            sLabel = TruncateLabel(sLabel);

            if (oEdgeEndpoint2.X < oEdgeEndpoint1.X)
            {
                // Don't let text be drawn upside-down.

                Point oTemp = oEdgeEndpoint2;
                oEdgeEndpoint2 = oEdgeEndpoint1;
                oEdgeEndpoint1 = oTemp;
            }

            Double dEdgeAngleDegrees = MathUtil.RadiansToDegrees(
                WpfGraphicsUtil.GetAngleBetweenPoints(
                    oEdgeEndpoint1, oEdgeEndpoint2));

            Double dEdgeLength = WpfGraphicsUtil.GetDistanceBetweenPoints(
                oEdgeEndpoint1, oEdgeEndpoint2);

            // To avoid trigonometric calculations, use a RotateTransform to make
            // the edge look as if it is horizontal, with oEdgeEndpoint2 to the
            // right of oEdgeEndpoint1.

            RotateTransform oRotateTransform = new RotateTransform(
                dEdgeAngleDegrees, oEdgeEndpoint1.X, oEdgeEndpoint1.Y);

            oEdgeEndpoint2         = oRotateTransform.Transform(oEdgeEndpoint2);
            oRotateTransform.Angle = -dEdgeAngleDegrees;
            oDrawingContext.PushTransform(oRotateTransform);

            FormattedText oFormattedText = CreateFormattedText(sLabel, oColor);

            oFormattedText.Trimming = TextTrimming.CharacterEllipsis;

            if (sLabel.IndexOf('\n') == -1)
            {
                // Unless the label includes line breaks, don't allow the
                // FormattedText class to break the text into multiple lines.

                oFormattedText.MaxLineCount = 1;
            }

            Double dTextWidth = oFormattedText.Width;

            // The ends of the label text are between one and two "buffer units"
            // from the ends of the edge.  The buffer unit is the width of an
            // arbitrary character.

            Double dBufferUnit             = CreateFormattedText("i", oColor).Width;
            Double dEdgeLengthMinusBuffers = dEdgeLength - 2 * dBufferUnit;

            if (dEdgeLengthMinusBuffers <= 0)
            {
                return;
            }

            // Determine where to draw the label text, and where to draw a
            // translucent rectangle behind the text.  The translucent rectangle
            // serves to obscure, but not completely hide, the underlying edge.

            Point oLabelOrigin = oEdgeEndpoint1;
            Rect  oTranslucentRectangle;

            if (dTextWidth > dEdgeLengthMinusBuffers)
            {
                // The label text should start one buffer unit from the first
                // endpoint, and terminate with ellipses approximately one buffer
                // length from the second endpoint.

                oLabelOrigin.Offset(dBufferUnit, 0);
                oFormattedText.MaxTextWidth = dEdgeLengthMinusBuffers;

                // The translucent rectangle should be the same width as the text.

                oTranslucentRectangle = new Rect(oLabelOrigin,
                                                 new Size(dEdgeLengthMinusBuffers, oFormattedText.Height));
            }
            else
            {
                // The label should be centered along the edge's length.

                oLabelOrigin.Offset(dEdgeLength / 2.0, 0);
                oFormattedText.TextAlignment = TextAlignment.Center;

                // The translucent rectangle should extend between zero and one
                // buffer units beyond the ends of the text.  This provides a
                // margin between the text and the unobscured edge, if there is
                // enough space.

                oTranslucentRectangle = new Rect(oLabelOrigin,

                                                 new Size(
                                                     Math.Min(dTextWidth + 2 * dBufferUnit,
                                                              dEdgeLengthMinusBuffers),

                                                     oFormattedText.Height)
                                                 );

                oTranslucentRectangle.Offset(
                    -oTranslucentRectangle.Width / 2.0, 0);
            }

            // The text and rectangle should be vertically centered on the edge.

            oDrawingContext.PushTransform(
                new TranslateTransform(0, -oFormattedText.Height / 2.0));

            // Draw the translucent rectangle, then the text.
            //
            // Note: Don't make the rectangle any more opaque than the edge, which
            // might be translucent itself.

            oDrawingContext.DrawRectangle(GetBrush(
                                              WpfGraphicsUtil.SetWpfColorAlpha(oGraphDrawingContext.BackColor,
                                                                               Math.Min(LabelBackgroundAlpha, oColor.A))
                                              ),
                                          null, oTranslucentRectangle);

            oDrawingContext.DrawText(oFormattedText, oLabelOrigin);

            oDrawingContext.Pop();
            oDrawingContext.Pop();
        }
Example #11
0
        TransferToGraphDrawer
        (
            GraphDrawer graphDrawer
        )
        {
            Debug.Assert(graphDrawer != null);
            AssertValid();

            System.Windows.Media.Typeface oTypeface;
            Double dFontSize;

            //***********
            //  Vertex
            //***********

            VertexDrawer oVertexDrawer = graphDrawer.VertexDrawer;

            FontToTypefaceAndFontSize(this.VertexFont,
                                      out oTypeface, out dFontSize);

            oVertexDrawer.SetFont(oTypeface, dFontSize);

            oVertexDrawer.LabelFillColor =
                WpfGraphicsUtil.ColorToWpfColor(this.VertexLabelFillColor);

            oVertexDrawer.LabelPosition      = this.VertexLabelPosition;
            oVertexDrawer.MaximumLabelLength = this.VertexLabelMaximumLength;
            oVertexDrawer.LabelWrapText      = this.VertexLabelWrapText;

            oVertexDrawer.LabelWrapMaxTextWidth =
                this.VertexLabelWrapMaxTextWidth;

            //***********
            //  Edge
            //***********

            EdgeDrawer oEdgeDrawer = graphDrawer.EdgeDrawer;

            FontToTypefaceAndFontSize(this.EdgeFont, out oTypeface, out dFontSize);

            oEdgeDrawer.SetFont(oTypeface, dFontSize);

            oEdgeDrawer.LabelTextColor =
                WpfGraphicsUtil.ColorToWpfColor(this.EdgeLabelTextColor);

            oEdgeDrawer.MaximumLabelLength = this.EdgeLabelMaximumLength;

            //***********
            //  Group
            //***********

            GroupDrawer oGroupDrawer = graphDrawer.GroupDrawer;

            FontToTypefaceAndFontSize(this.GroupFont,
                                      out oTypeface, out dFontSize);

            oGroupDrawer.SetFont(oTypeface, dFontSize);

            oGroupDrawer.LabelTextColor = WpfGraphicsUtil.ColorToWpfColor(

                Color.FromArgb((new AlphaConverter()).WorkbookToGraphAsByte(
                                   this.GroupLabelTextAlpha),

                               this.GroupLabelTextColor)
                );

            oGroupDrawer.LabelPosition = this.GroupLabelPosition;
        }
Example #12
0
        SaveGraphImageFile
        (
            NodeXLControl oNodeXLControl,
            IEnumerable <LegendControlBase> oLegendControls,
            String sWorkbookFilePath
        )
        {
            Debug.Assert(oNodeXLControl != null);
            Debug.Assert(oLegendControls != null);
            Debug.Assert(!String.IsNullOrEmpty(sWorkbookFilePath));

            AutomatedGraphImageUserSettings oAutomatedGraphImageUserSettings =
                new AutomatedGraphImageUserSettings();

            System.Drawing.Size oImageSizePx =
                oAutomatedGraphImageUserSettings.ImageSizePx;

            Int32 iWidth  = oImageSizePx.Width;
            Int32 iHeight = oImageSizePx.Height;

            Boolean bIncludeHeader = oAutomatedGraphImageUserSettings.IncludeHeader;
            Boolean bIncludeFooter = oAutomatedGraphImageUserSettings.IncludeFooter;

            Debug.Assert(!bIncludeHeader ||
                         oAutomatedGraphImageUserSettings.HeaderText != null);

            Debug.Assert(!bIncludeFooter ||
                         oAutomatedGraphImageUserSettings.FooterText != null);

            GraphImageCompositor oGraphImageCompositor =
                new GraphImageCompositor(oNodeXLControl);

            UIElement oCompositeElement = oGraphImageCompositor.Composite(
                iWidth, iHeight,
                bIncludeHeader ? oAutomatedGraphImageUserSettings.HeaderText : null,
                bIncludeFooter ? oAutomatedGraphImageUserSettings.FooterText : null,
                oAutomatedGraphImageUserSettings.HeaderFooterFont, oLegendControls
                );

            System.Drawing.Bitmap oBitmap = WpfGraphicsUtil.VisualToBitmap(
                oCompositeElement, iWidth, iHeight);

            ImageFormat eImageFormat =
                oAutomatedGraphImageUserSettings.ImageFormat;

            String sImageFilePath = Path.ChangeExtension(sWorkbookFilePath,
                                                         SaveableImageFormats.GetFileExtension(eImageFormat));

            try
            {
                oBitmap.Save(sImageFilePath, eImageFormat);
            }
            catch (System.Runtime.InteropServices.ExternalException)
            {
                // When an image file already exists and is read-only, an
                // ExternalException is thrown.
                //
                // Note that this method is called from the
                // ThisWorkbook.GraphLaidOut event handler, so this exception can't
                // be handled by a TaskAutomator.AutomateOneWorkbook() exception
                // handler.

                FormUtil.ShowWarning(String.Format(
                                         "The image file \"{0}\" couldn't be saved.  Does a read-only"
                                         + " file with the same name already exist?"
                                         ,
                                         sImageFilePath
                                         ));
            }
            finally
            {
                oBitmap.Dispose();

                oGraphImageCompositor.RestoreNodeXLControl();
            }
        }