Example #1
0
        UndrawVertex
        (
            IVertex vertex,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(vertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Retrieve the VertexDrawingHistory object for the vertex, if one
            // exists.  (If the vertex was previously hidden, there won't be a
            // VertexDrawingHistory object for it.)

            Dictionary <Int32, VertexDrawingHistory> oVertexDrawingHistories =
                graphDrawingContext.VertexDrawingHistories;

            Int32 iVertexID = vertex.ID;
            VertexDrawingHistory oVertexDrawingHistory;

            if (oVertexDrawingHistories.TryGetValue(
                    iVertexID, out oVertexDrawingHistory))
            {
                // Remove the VertexDrawingHistory object from the dictionary.

                oVertexDrawingHistories.Remove(iVertexID);

                // Remove the vertex's DrawingVisual object, which will cause the
                // vertex to disappear.

                m_oAllVertexDrawingVisuals.Children.Remove(
                    oVertexDrawingHistory.DrawingVisual);
            }
        }
Example #2
0
        DrawEdge
        (
            IEdge oEdge,
            GraphDrawingContext oGraphDrawingContext
        )
        {
            Debug.Assert(oEdge != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            EdgeDrawingHistory oEdgeDrawingHistory;

            Dictionary <Int32, EdgeDrawingHistory> oEdgeDrawingHistories =
                oGraphDrawingContext.EdgeDrawingHistories;

            if (m_oEdgeDrawer.TryDrawEdge(oEdge, oGraphDrawingContext,
                                          out oEdgeDrawingHistory))
            {
                Debug.Assert(oEdgeDrawingHistory != null);

                GetEdgeDrawingVisuals(oEdgeDrawingHistory).Children.Add(
                    oEdgeDrawingHistory.DrawingVisual);

                // Save the EdgeDrawingHistory object.

                oEdgeDrawingHistories.Add(oEdge.ID, oEdgeDrawingHistory);
            }
        }
Example #3
0
        UndrawEdge
        (
            IEdge edge,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Retrieve the EdgeDrawingHistory object for the edge, if one exists.
            // (If the edge was previously hidden, there won't be an
            // EdgeDrawingHistory object for it.)

            Dictionary <Int32, EdgeDrawingHistory> oEdgeDrawingHistories =
                graphDrawingContext.EdgeDrawingHistories;

            Int32 iEdgeID = edge.ID;
            EdgeDrawingHistory oEdgeDrawingHistory;

            if (oEdgeDrawingHistories.TryGetValue(
                    iEdgeID, out oEdgeDrawingHistory))
            {
                // Remove the EdgeDrawingHistory object from the dictionary.

                oEdgeDrawingHistories.Remove(iEdgeID);

                // Remove the edge's DrawingVisual object, which will cause the
                // edge to disappear.

                GetEdgeDrawingVisuals(oEdgeDrawingHistory).Children.Remove(
                    oEdgeDrawingHistory.DrawingVisual);
            }
        }
Example #4
0
        DrawNewVertex
        (
            IVertex newVertex,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(newVertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            DrawVertex(newVertex, graphDrawingContext);
        }
Example #5
0
        DrawNewEdge
        (
            IEdge newEdge,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(newEdge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            DrawEdge(newEdge, graphDrawingContext);
        }
Example #6
0
        RedrawEdge
        (
            IEdge edge,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            UndrawEdge(edge, graphDrawingContext);
            DrawEdge(edge, graphDrawingContext);
        }
Example #7
0
        RedrawVertex
        (
            IVertex vertex,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(vertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            UndrawVertex(vertex, graphDrawingContext);
            DrawVertex(vertex, graphDrawingContext);
        }
Example #8
0
        TryGetEdgeEndpoints
        (
            IVertex oVertex1,
            IVertex oVertex2,
            GraphDrawingContext oGraphDrawingContext,
            out Point oEdgeEndpoint1,
            out Point oEdgeEndpoint2
        )
        {
            Debug.Assert(oVertex1 != null);
            Debug.Assert(oVertex2 != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            oEdgeEndpoint1 = new Point();
            oEdgeEndpoint2 = new Point();

            // Retrieve the information about how the vertices were drawn.

            Dictionary <Int32, VertexDrawingHistory> oVertexDrawingHistories =
                oGraphDrawingContext.VertexDrawingHistories;

            VertexDrawingHistory oVertex1DrawingHistory, oVertex2DrawingHistory;

            if (
                !oVertexDrawingHistories.TryGetValue(oVertex1.ID,
                                                     out oVertex1DrawingHistory)
                ||
                !oVertexDrawingHistories.TryGetValue(oVertex2.ID,
                                                     out oVertex2DrawingHistory)
                )
            {
                // One of the edge's vertices is hidden.

                return(false);
            }

            // The drawing histories determine the edge endpoints.  For example, if
            // oVertex1 was drawn as a circle, then oVertex1DrawingHistory is a
            // CircleVertexDrawingHistory that knows to put its endpoint on the
            // circle itself and not at the circle's center.

            oVertex1DrawingHistory.GetEdgeEndpoint(oVertex2DrawingHistory,
                                                   out oEdgeEndpoint1);

            oVertex2DrawingHistory.GetEdgeEndpoint(oVertex1DrawingHistory,
                                                   out oEdgeEndpoint2);

            return(true);
        }
Example #9
0
        CreateVisual
        (
            Point currentMouseLocation,
            Color backColor,
            VertexDrawer vertexDrawer
        )
        {
            Debug.Assert(vertexDrawer != null);
            Debug.Assert(m_bDragIsInProgress);
            AssertValid();

            // This method redraws the dragged vertices at an offset location, and
            // adds the resulting Visuals to a ContainerVisual.
            //
            // Figure out the offset.

            Double dOffsetX = currentMouseLocation.X - m_oMouseDownLocation.X;
            Double dOffsetY = currentMouseLocation.Y - m_oMouseDownLocation.Y;

            GraphDrawingContext oGraphDrawingContext = new GraphDrawingContext(
                m_oGraphRectangle, m_iMargin, backColor);

            ContainerVisual oContainerVisual = new ContainerVisual();

            foreach (IVertex oVertex in m_aoVertices)
            {
                System.Drawing.PointF oOriginalLocation =
                    GetOriginalVertexLocation(oVertex);

                oVertex.Location = new System.Drawing.PointF(
                    oOriginalLocation.X + (Single)dOffsetX,
                    oOriginalLocation.Y + (Single)dOffsetY
                    );

                VertexDrawingHistory oVertexDrawingHistory;

                if (vertexDrawer.TryDrawVertex(oVertex, oGraphDrawingContext,
                                               out oVertexDrawingHistory))
                {
                    oContainerVisual.Children.Add(
                        oVertexDrawingHistory.DrawingVisual);
                }
            }

            m_oVisual = oContainerVisual;

            return(m_oVisual);
        }
Example #10
0
        TryDrawSelfLoop
        (
            IVertex oVertex,
            DrawingContext oDrawingContext,
            GraphDrawingContext oGraphDrawingContext,
            Color oColor,
            Double dWidth,
            Boolean bDrawArrow
        )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(dWidth >= 0);
            AssertValid();

            // Retrieve the information about how the vertex was drawn.

            VertexDrawingHistory oVertexDrawingHistory;

            if (!oGraphDrawingContext.VertexDrawingHistories.TryGetValue(
                    oVertex.ID, out oVertexDrawingHistory))
            {
                // The edge's vertex is hidden, so the edge should be hidden also.

                return(false);
            }

            // Determine the edge of the graph rectangle that is farthest from the
            // vertex.

            Point oVertexLocation = oVertexDrawingHistory.VertexLocation;

            RectangleEdge eFarthestGraphRectangleEdge =
                WpfGraphicsUtil.GetFarthestRectangleEdge(oVertexLocation,
                                                         oGraphDrawingContext.GraphRectangle);

            // Get the point on the vertex at which to draw the self-loop.

            Point oSelfLoopEndpoint = oVertexDrawingHistory.GetSelfLoopEndpoint(
                eFarthestGraphRectangleEdge);

            DrawSelfLoopAt(oDrawingContext, oGraphDrawingContext, oColor, dWidth,
                           oSelfLoopEndpoint, eFarthestGraphRectangleEdge, bDrawArrow);

            return(true);
        }
Example #11
0
        DrawBackground
        (
            IGraph oGraph,
            GraphDrawingContext oGraphDrawingContext
        )
        {
            Debug.Assert(oGraph != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            // Draw the background color, followed by the background image if one
            // was specified.

            Color oBackColor;

            if (!TryGetColorValue(oGraph, ReservedMetadataKeys.GraphBackColor,
                                  out oBackColor))
            {
                oBackColor = m_oBackColor;
            }

            DrawingVisual oBackgroundDrawingVisual = new DrawingVisual();

            using (DrawingContext oDrawingContext =
                       oBackgroundDrawingVisual.RenderOpen())
            {
                oDrawingContext.DrawRectangle(
                    CreateFrozenSolidColorBrush(oBackColor), null,
                    oGraphDrawingContext.GraphRectangle);

                Object oImageSourceAsObject;

                if (oGraph.TryGetValue(ReservedMetadataKeys.GraphBackgroundImage,
                                       typeof(ImageSource), out oImageSourceAsObject))
                {
                    ImageSource oImageSource = (ImageSource)oImageSourceAsObject;

                    oDrawingContext.DrawImage(oImageSource,
                                              new Rect(new Size(oImageSource.Width,
                                                                oImageSource.Height)));
                }
            }

            m_oVisualCollection.Add(oBackgroundDrawingVisual);
        }
Example #12
0
        DrawLabel
        (
            DrawingContext drawingContext,
            GraphDrawingContext graphDrawingContext,
            VertexDrawingHistory vertexDrawingHistory,
            Rect vertexBounds,
            FormattedText formattedText
        )
        {
            Debug.Assert(drawingContext != null);
            Debug.Assert(graphDrawingContext != null);
            Debug.Assert(vertexDrawingHistory != null);
            Debug.Assert(formattedText != null);
            AssertValid();

            DrawLabel(drawingContext, graphDrawingContext, vertexDrawingHistory,
                      vertexBounds, GetLabelPosition(vertexDrawingHistory.Vertex),
                      formattedText);
        }
Example #13
0
        DrawVertex
        (
            IVertex oVertex,
            GraphDrawingContext oGraphDrawingContext
        )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            VertexDrawingHistory oVertexDrawingHistory;

            Dictionary <Int32, VertexDrawingHistory> oVertexDrawingHistories =
                oGraphDrawingContext.VertexDrawingHistories;

            if (m_oVertexDrawer.TryDrawVertex(oVertex, oGraphDrawingContext,
                                              out oVertexDrawingHistory))
            {
                Debug.Assert(oVertexDrawingHistory != null);

                // Add the DrawingVisual for the vertex to
                // m_oAllVertexDrawingVisuals, and add the VertexDrawingHistory to
                // the oGraphDrawingContext.VertexDrawingHistories dictionary.

                DrawingVisual oVertexChildDrawingVisual =
                    oVertexDrawingHistory.DrawingVisual;

                m_oAllVertexDrawingVisuals.Children.Add(oVertexChildDrawingVisual);

                oVertexDrawingHistories.Add(oVertex.ID, oVertexDrawingHistory);

                // Save the vertex on the DrawingVisual for later retrieval.

                SaveVertexOnDrawingVisual(oVertex, oVertexChildDrawingVisual);
            }
        }
Example #14
0
        //*************************************************************************
        //  Method: DrawImageShape()
        //
        /// <summary>
        /// Draws a vertex as a specified image.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex to draw.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="oDrawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="oDrawingVisual">
        /// The <see cref="DrawingVisual" /> object from which <paramref
        /// name="oDrawingContext" /> was obtained.
        /// </param>
        ///
        /// <param name="eVisibility">
        /// The visibility of the vertex.
        /// </param>
        ///
        /// <param name="bDrawAsSelected">
        /// true to draw the vertex as selected.
        /// </param>
        ///
        /// <param name="sAnnotation">
        /// The annotation to draw next to the image, or null if there is no
        /// annotation.
        /// </param>
        ///
        /// <param name="oImageSource">
        /// The image to draw.
        /// </param>
        ///
        /// <param name="oVertexLabelDrawer">
        /// Object that draws a vertex label as an annotation.
        /// </param>
        ///
        /// <returns>
        /// A VertexDrawingHistory object that retains information about how the
        /// vertex was drawn.
        /// </returns>
        //*************************************************************************
        protected VertexDrawingHistory DrawImageShape(
            IVertex oVertex,
            GraphDrawingContext oGraphDrawingContext,
            DrawingContext oDrawingContext,
            DrawingVisual oDrawingVisual,
            VisibilityKeyValue eVisibility,
            Boolean bDrawAsSelected,
            String sAnnotation,
            ImageSource oImageSource,
            VertexLabelDrawer oVertexLabelDrawer
            )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oDrawingVisual != null);
            Debug.Assert(oImageSource != null);
            Debug.Assert(oVertexLabelDrawer != null);
            AssertValid();

            // Move the vertex if it falls outside the graph rectangle.

            Rect oVertexRectangle = GetVertexRectangle(
            GetVertexLocation(oVertex), oImageSource.Width * m_dGraphScale,
            oImageSource.Height * m_dGraphScale);

            MoveVertexIfNecessary(oVertex, ref oVertexRectangle,
            oGraphDrawingContext);

            Byte btAlpha = 255;

            if (!bDrawAsSelected)
            {
            // Check for a non-opaque alpha value.

            btAlpha = GetAlpha(oVertex, eVisibility, btAlpha);
            }

            VertexDrawingHistory oVertexDrawingHistory =
            new ImageVertexDrawingHistory(oVertex, oDrawingVisual,
                bDrawAsSelected, oVertexRectangle);

            if (btAlpha > 0)
            {
            oDrawingContext.DrawImage(oImageSource, oVertexRectangle);

            Color oColor = GetColor(oVertex, eVisibility, bDrawAsSelected);

            // Draw an outline rectangle.

            oDrawingContext.DrawRectangle(null,
                GetPen(oColor, DefaultPenThickness), oVertexRectangle);

            if (btAlpha < 255)
            {
                // Real transparency can't be achieved with arbitrary images,
                // so simulate transparency by drawing on top of the image with
                // a translucent brush the same color as the graph's
                // background.
                //
                // This really isn't a good solution.  Is there are better way
                // to simulate transparency?

                Color oTranslucentColor = oGraphDrawingContext.BackColor;
                oTranslucentColor.A = (Byte)( (Byte)255 - btAlpha );

                oDrawingContext.DrawRectangle(
                    CreateFrozenSolidColorBrush(oTranslucentColor), null,
                        oVertexRectangle);
            }

            if (sAnnotation != null)
            {
                oVertexLabelDrawer.DrawLabel(oDrawingContext,
                    oGraphDrawingContext, oVertexDrawingHistory,
                    oVertexRectangle, CreateFormattedText(sAnnotation, oColor)
                    );
            }
            }

            return (oVertexDrawingHistory);
        }
Example #15
0
        //*************************************************************************
        //  Method: DrawLabelShape()
        //
        /// <summary>
        /// Draws a vertex as a label.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex to draw.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="oDrawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="oDrawingVisual">
        /// The <see cref="DrawingVisual" /> object from which <paramref
        /// name="oDrawingContext" /> was obtained.
        /// </param>
        ///
        /// <param name="eVisibility">
        /// The visibility of the vertex.
        /// </param>
        ///
        /// <param name="bDrawAsSelected">
        /// true to draw the vertex as selected.
        /// </param>
        ///
        /// <param name="sLabel">
        /// The label to draw.  Can't be null or empty.
        /// </param>
        ///
        /// <returns>
        /// A VertexDrawingHistory object that retains information about how the
        /// vertex was drawn.
        /// </returns>
        //*************************************************************************
        protected VertexDrawingHistory DrawLabelShape(
            IVertex oVertex,
            GraphDrawingContext oGraphDrawingContext,
            DrawingContext oDrawingContext,
            DrawingVisual oDrawingVisual,
            VisibilityKeyValue eVisibility,
            Boolean bDrawAsSelected,
            String sLabel
            )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oDrawingVisual != null);
            Debug.Assert( !String.IsNullOrEmpty(sLabel) );
            AssertValid();

            // Figure out what colors to use.

            Color oOutlineColor;

            Color oTextColor = GetColor(oVertex, eVisibility, false);

            Color oFillColor = GetColor(oVertex, eVisibility,
            ReservedMetadataKeys.PerVertexLabelFillColor, m_oLabelFillColor,
            true);

            if (bDrawAsSelected)
            {
            // The outline color is always the selected color.

            oOutlineColor = m_oSelectedColor;

            // The text color is the default or per-vertex color with no alpha.

            oTextColor.A = 255;

            // The fill color is the default or per-vertex fill color with no
            // alpha.

            oFillColor.A = 255;
            }
            else
            {
            // The outline color is the default or per-vertex color with alpha.

            oOutlineColor = oTextColor;

            // The text color is the default or per-vertex color with alpha.

            // The fill color is the default or per-vertex fill color with
            // alpha.
            }

            Double dLabelFontSize = GetLabelFontSize(oVertex);

            // Format the text, subject to a maximum label size.  If a maximum
            // label size isn't specified, the label would be as wide as necessary
            // to accommodate the text length.  Specifying a maximum size forces
            // the text to wrap at word breaks.
            //
            // Side effect: If the font size is large enough, not a single
            // character of the text will fit within the specified width and no
            // text will be drawn.

            FormattedText oFormattedText = CreateFormattedText(sLabel, oTextColor,
            dLabelFontSize);

            oFormattedText.MaxTextWidth = MaximumLabelWidth * m_dGraphScale;
            oFormattedText.MaxTextHeight = MaximumLabelHeight * m_dGraphScale;

            Rect oVertexRectangle = GetVertexRectangle(
            GetVertexLocation(oVertex), oFormattedText.Width,
            oFormattedText.Height);

            // Pad the text.

            Rect oVertexRectangleWithPadding = oVertexRectangle;
            Double dLabelPadding = GetLabelPadding(dLabelFontSize);

            oVertexRectangleWithPadding.Inflate(dLabelPadding,
            dLabelPadding * 0.7);

            if (m_oTypeface.Style != FontStyles.Normal)
            {
            // This is a hack to move the right edge of the padded rectangle
            // to the right to adjust for wider italic text, which
            // FormattedText.Width does not account for.  What is the correct
            // way to do this?  It might involve the FormattedText.Overhang*
            // properties, but I'll be darned if I can understand how those
            // properties work.

            Double dItalicCompensation = dLabelFontSize / 7.0;
            oVertexRectangleWithPadding.Inflate(dItalicCompensation, 0);
            oVertexRectangleWithPadding.Offset(dItalicCompensation, 0);
            }

            // Move the vertex if it falls outside the graph rectangle.

            Double dOriginalVertexRectangleWithPaddingX =
            oVertexRectangleWithPadding.X;

            Double dOriginalVertexRectangleWithPaddingY =
            oVertexRectangleWithPadding.Y;

            MoveVertexIfNecessary(oVertex, ref oVertexRectangleWithPadding,
            oGraphDrawingContext);

            oVertexRectangle.Offset(

            oVertexRectangleWithPadding.X -
                dOriginalVertexRectangleWithPaddingX,

            oVertexRectangleWithPadding.Y -
                dOriginalVertexRectangleWithPaddingY
            );

            // Draw the padded rectangle, then the text.

            oDrawingContext.DrawRectangle( GetBrush(oFillColor),
            GetPen(oOutlineColor, DefaultPenThickness),
            oVertexRectangleWithPadding);

            oDrawingContext.DrawText(oFormattedText, oVertexRectangle.Location);

            // Return information about how the vertex was drawn.

            return ( new LabelVertexDrawingHistory(oVertex, oDrawingVisual,
            bDrawAsSelected, oVertexRectangleWithPadding) );
        }
Example #16
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 #17
0
        //*************************************************************************
        //  Method: CheckDrawVertexArguments()
        //
        /// <summary>
        /// Checks the arguments to <see cref="TryDrawVertex" />.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex that will eventually be drawn.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <remarks>
        /// An exception is thrown if one of the arguments is invalid.
        /// </remarks>
        //*************************************************************************
        protected void CheckDrawVertexArguments(
            IVertex oVertex,
            GraphDrawingContext oGraphDrawingContext
            )
        {
            AssertValid();

            const String MethodName = "TryDrawVertex";
            const String VertexArgumentName = "vertex";

            ArgumentChecker oArgumentChecker = this.ArgumentChecker;

            oArgumentChecker.CheckArgumentNotNull(MethodName, VertexArgumentName,
            oVertex);

            oArgumentChecker.CheckArgumentNotNull(MethodName,
            "graphDrawingContext", oGraphDrawingContext);

            if (oVertex.ParentGraph == null)
            {
            oArgumentChecker.ThrowArgumentException(
                MethodName, VertexArgumentName,
                "The vertex doesn't belong to a graph.  It can't be drawn."
                );
            }
        }
Example #18
0
        //*************************************************************************
        //  Method: DrawGraph()
        //
        /// <summary>
        /// Draws a laid-out graph onto the contained collection of Visual objects.
        /// </summary>
        ///
        /// <param name="graph">
        /// The graph to draw onto the contained collection of Visual objects.  The
        /// graph should have already been laid out.  You can use one of the
        /// supplied layout classes to do this.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <remarks>
        /// If you want to add a Visual on top of the graph, call <see
        /// cref="AddVisualOnTopOfGraph" /> after this method returns.
        ///
        /// <para>
        /// The collection of Visual objects is accessible via the <see
        /// cref="GraphDrawer.VisualCollection" /> property.
        /// </para>
        ///
        /// </remarks>
        //*************************************************************************
        public void DrawGraph(
            IGraph graph,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(graph != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Implementation note:
            //
            // In a previous GDI+ implementation of this graph drawer, the edges
            // had to be drawn first to allow the vertices to cover the ends of the
            // edges.  That required a complex three-step drawing process: 1) allow
            // the vertex drawer to move each vertex if necessary to prevent the
            // vertex from falling outside the graph rectangle; 2) draw the edges
            // using the moved vertex locations; and 3) draw the vertices.
            //
            // This WPF implementation is simpler, for two reasons:
            //
            // 1. WPF uses retained-mode graphics, so covering the ends of the
            //    edges can be accomplished simply by adding
            //    m_oUnselectedEdgeDrawingVisuals to m_oVisualCollection before
            //    adding m_oAllVertexDrawingVisuals.  That means that the vertices
            //    can be drawn onto m_oAllVertexDrawingVisuals first, and the
            //    vertex drawer can move the vertices as necessary before drawing
            //    them.  A three-step process is no longer required.
            //
            // 2. The edges in this implementation don't actually need to be
            //    covered, because they terminate at the vertex boundaries instead
            //    of the vertex centers, as in the GDI+ implementation.

            m_oVisualCollection.Clear();

            DrawBackground(graph, graphDrawingContext);

            m_oAllVertexDrawingVisuals = new DrawingVisual();
            m_oUnselectedEdgeDrawingVisuals = new DrawingVisual();
            m_oSelectedEdgeDrawingVisuals = new DrawingVisual();

            // Draw the vertices after moving them if necessary.  Each vertex needs
            // to be individually hit-tested and possibly redrawn by
            // RedrawVertex(), so each vertex is put into its own DrawingVisual
            // that becomes a child of m_oAllVertexDrawingVisuals.

            foreach (IVertex oVertex in graph.Vertices)
            {
            DrawVertex(oVertex, graphDrawingContext);
            }

            // Draw the edges.  The edges don't need to be hit-tested, but they
            // might need to be redrawn by RedrawEdge(), so each edge is put into
            // its own DrawingVisual that becomes a child of either
            // m_oUnselectedEdgeDrawingVisuals or m_oSelectedEdgeDrawingVisuals.

            foreach (IEdge oEdge in graph.Edges)
            {
            DrawEdge(oEdge, graphDrawingContext);
            }

            // Selected edges need to be drawn on top of all the vertices
            // (including selected vertices) to guarantee that they will be
            // visible; hence the addition order seen here.

            m_oVisualCollection.Add(m_oUnselectedEdgeDrawingVisuals);
            m_oVisualCollection.Add(m_oAllVertexDrawingVisuals);
            m_oVisualCollection.Add(m_oSelectedEdgeDrawingVisuals);
        }
Example #19
0
        //*************************************************************************
        //  Method: DrawNewVertex()
        //
        /// <summary>
        /// Draws a vertex that has been added to the graph but not yet drawn by
        /// <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="newVertex">
        /// The new vertex to draw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to draw a new vertex without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void DrawNewVertex(
            IVertex newVertex,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(newVertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            DrawVertex(newVertex, graphDrawingContext);
        }
Example #20
0
        //*************************************************************************
        //  Method: DrawLabel()
        //
        /// <summary>
        /// Draws a vertex label as an annotation.
        /// </summary>
        ///
        /// <summary>
        /// Draws a vertex label as an annotation at a position determined by the
        /// vertex's metadata.
        /// </summary>
        ///
        /// <param name="drawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="vertexDrawingHistory">
        /// Describes how the vertex was drawn.
        /// </param>
        ///
        /// <param name="vertexBounds">
        /// The vertex's bounding rectangle.
        /// </param>
        ///
        /// <param name="formattedText">
        /// The FormattedText object to use.  Several properties get changed by
        /// this method.
        /// </param>
        //*************************************************************************
        public void DrawLabel(
            DrawingContext drawingContext,
            GraphDrawingContext graphDrawingContext,
            VertexDrawingHistory vertexDrawingHistory,
            Rect vertexBounds,
            FormattedText formattedText
            )
        {
            Debug.Assert(drawingContext != null);
            Debug.Assert(graphDrawingContext != null);
            Debug.Assert(vertexDrawingHistory != null);
            Debug.Assert(formattedText != null);
            AssertValid();

            DrawLabel(drawingContext, graphDrawingContext, vertexDrawingHistory,
            vertexBounds, GetLabelPosition(vertexDrawingHistory.Vertex),
            formattedText);
        }
Example #21
0
        //*************************************************************************
        //  Method: DrawEdge()
        //
        /// <summary>
        /// Draws an edge onto the contained collection of Visual objects.
        /// </summary>
        ///
        /// <param name="oEdge">
        /// The edge to draw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <remarks>
        /// This method adds a DrawingVisual for the edge to either
        /// m_oUnselectedEdgeDrawingVisuals or m_oSelectedEdgeDrawingVisuals, and
        /// adds an EdgeDrawingHistory to
        /// oGraphDrawingContext.EdgeDrawingHistories.
        /// </remarks>
        //*************************************************************************
        protected void DrawEdge(
            IEdge oEdge,
            GraphDrawingContext oGraphDrawingContext
            )
        {
            Debug.Assert(oEdge != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            EdgeDrawingHistory oEdgeDrawingHistory;

            Dictionary<Int32, EdgeDrawingHistory> oEdgeDrawingHistories =
            oGraphDrawingContext.EdgeDrawingHistories;

            if ( m_oEdgeDrawer.TryDrawEdge(oEdge, oGraphDrawingContext,
            out oEdgeDrawingHistory) )
            {
            Debug.Assert(oEdgeDrawingHistory != null);

            GetEdgeDrawingVisuals(oEdgeDrawingHistory).Children.Add(
                oEdgeDrawingHistory.DrawingVisual);

            // Save the EdgeDrawingHistory object.

            oEdgeDrawingHistories.Add(oEdge.ID, oEdgeDrawingHistory);
            }
        }
Example #22
0
        //*************************************************************************
        //  Method: RedrawVertex()
        //
        /// <summary>
        /// Redraws a vertex that was drawn by <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="vertex">
        /// The vertex to redraw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to redraw a vertex whose attributes (such as its
        /// selected state) have changed without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void RedrawVertex(
            IVertex vertex,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(vertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            UndrawVertex(vertex, graphDrawingContext);
            DrawVertex(vertex, graphDrawingContext);
        }
Example #23
0
        //*************************************************************************
        //  Method: UndrawVertex()
        //
        /// <summary>
        /// "Undraws" a vertex that was drawn by <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="vertex">
        /// The vertex to remove from the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to undraw a vertex without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void UndrawVertex(
            IVertex vertex,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(vertex != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Retrieve the VertexDrawingHistory object for the vertex, if one
            // exists.  (If the vertex was previously hidden, there won't be a
            // VertexDrawingHistory object for it.)

            Dictionary<Int32, VertexDrawingHistory> oVertexDrawingHistories =
            graphDrawingContext.VertexDrawingHistories;

            Int32 iVertexID = vertex.ID;
            VertexDrawingHistory oVertexDrawingHistory;

            if ( oVertexDrawingHistories.TryGetValue(
            iVertexID, out oVertexDrawingHistory) )
            {
            // Remove the VertexDrawingHistory object from the dictionary.

            oVertexDrawingHistories.Remove(iVertexID);

            // Remove the vertex's DrawingVisual object, which will cause the
            // vertex to disappear.

            m_oAllVertexDrawingVisuals.Children.Remove(
                oVertexDrawingHistory.DrawingVisual);
            }
        }
Example #24
0
        //*************************************************************************
        //  Method: CreateVisual()
        //
        /// <summary>
        /// Creates the Visual that should be used to represent the dragged
        /// vertices.
        /// </summary>
        ///
        /// <param name="currentMouseLocation">
        /// The current mouse location.
        /// </param>
        ///
        /// <param name="backColor">
        /// The graph's background color.
        /// </param>
        ///
        /// <param name="vertexDrawer">
        /// The VertexDrawer that should be used to draw the dragged vertices.
        /// </param>
        ///
        /// <returns>
        /// The Visual that should be used to represent the dragged vertices.
        /// </returns>
        ///
        /// <remarks>
        /// The returned Visual can be retrieved later via the <see
        /// cref="MouseDragWithVisual.Visual" /> property.
        /// </remarks>
        //*************************************************************************
        public Visual CreateVisual(
            Point currentMouseLocation,
            Color backColor,
            VertexDrawer vertexDrawer
            )
        {
            Debug.Assert(vertexDrawer != null);
            Debug.Assert(m_bDragIsInProgress);
            AssertValid();

            // This method redraws the dragged vertices at an offset location, and
            // adds the resulting Visuals to a ContainerVisual.
            //
            // Figure out the offset.

            Double dOffsetX = currentMouseLocation.X - m_oMouseDownLocation.X;
            Double dOffsetY = currentMouseLocation.Y - m_oMouseDownLocation.Y;

            GraphDrawingContext oGraphDrawingContext = new GraphDrawingContext(
            m_oGraphRectangle, m_iMargin, backColor);

            ContainerVisual oContainerVisual = new ContainerVisual();

            foreach (IVertex oVertex in m_aoVertices)
            {
            System.Drawing.PointF oOriginalLocation =
                GetOriginalVertexLocation(oVertex);

            oVertex.Location = new System.Drawing.PointF(
                oOriginalLocation.X + (Single)dOffsetX,
                oOriginalLocation.Y + (Single)dOffsetY
                );

            VertexDrawingHistory oVertexDrawingHistory;

            if ( vertexDrawer.TryDrawVertex(oVertex, oGraphDrawingContext,
                out oVertexDrawingHistory) )
            {
                oContainerVisual.Children.Add(
                    oVertexDrawingHistory.DrawingVisual);
            }
            }

            m_oVisual = oContainerVisual;

            return (m_oVisual);
        }
Example #25
0
        //*************************************************************************
        //  Method: DrawLabel()
        //
        /// <summary>
        /// Draws a vertex label as an annotation at a specified position.
        /// </summary>
        ///
        /// <param name="drawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="vertexDrawingHistory">
        /// Describes how the vertex was drawn.
        /// </param>
        ///
        /// <param name="vertexBounds">
        /// The vertex's bounding rectangle.
        /// </param>
        ///
        /// <param name="labelPosition">
        /// The label's position.
        /// </param>
        ///
        /// <param name="formattedText">
        /// The FormattedText object to use.  Several properties get changed by
        /// this method.
        /// </param>
        //*************************************************************************
        public void DrawLabel(
            DrawingContext drawingContext,
            GraphDrawingContext graphDrawingContext,
            VertexDrawingHistory vertexDrawingHistory,
            Rect vertexBounds,
            VertexLabelPosition labelPosition,
            FormattedText formattedText
            )
        {
            Debug.Assert(drawingContext != null);
            Debug.Assert(graphDrawingContext != null);
            Debug.Assert(vertexDrawingHistory != null);
            Debug.Assert(formattedText != null);
            AssertValid();

            Double dHalfVertexBoundsWidth = vertexBounds.Width / 2.0;
            Double dHalfVertexBoundsHeight = vertexBounds.Height / 2.0;
            Double dLabelHeight = formattedText.Height;
            Double dHalfLabelHeight = dLabelHeight / 2.0;
            Double dLabelWidth = formattedText.Width;
            Double dHalfLabelWidth = dLabelWidth / 2.0;
            TextAlignment eTextAlignment = TextAlignment.Left;

            formattedText.MaxLineCount = 1;

            // This is the point where the label will be drawn.  It initially
            // assumes a text height of zero with no margin, but that will be
            // adjusted within the switch statement below.

            Point oDraw = vertexDrawingHistory.GetLabelLocation(labelPosition);
            Double dDrawX = oDraw.X;
            Double dDrawY = oDraw.Y;

            // These are the bounds of the label text.

            Double dLabelBoundsLeft = 0;
            Double dLabelBoundsRight = 0;

            switch (labelPosition)
            {
            case VertexLabelPosition.TopLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawY -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.TopCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.TopRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawY -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            case VertexLabelPosition.MiddleLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawX -= HorizontalMargin;
                dDrawY -= dHalfLabelHeight;
                dLabelBoundsLeft = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.MiddleCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY -= dHalfLabelHeight;
                dLabelBoundsLeft = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.MiddleRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawX += HorizontalMargin;
                dDrawY -= dHalfLabelHeight;
                dLabelBoundsLeft = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            case VertexLabelPosition.BottomLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawY += VerticalMargin;
                dLabelBoundsLeft = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.BottomCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY += VerticalMargin;
                dLabelBoundsLeft = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.BottomRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawY += VerticalMargin;
                dLabelBoundsLeft = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            default:

                Debug.Assert(false);
                break;
            }

            // Don't let the text exceed the bounds of the graph rectangle.

            Double dLabelBoundsTop = dDrawY;
            Double dLabelBoundsBottom = dDrawY + dLabelHeight;

            Rect oGraphRectangleMinusMargin =
            graphDrawingContext.GraphRectangleMinusMargin;

            dDrawX += Math.Max(0,
            oGraphRectangleMinusMargin.Left - dLabelBoundsLeft);

            dDrawX -= Math.Max(0,
            dLabelBoundsRight - oGraphRectangleMinusMargin.Right);

            dDrawY += Math.Max(0,
            oGraphRectangleMinusMargin.Top - dLabelBoundsTop);

            dDrawY -= Math.Max(0,
            dLabelBoundsBottom - oGraphRectangleMinusMargin.Bottom);

            formattedText.TextAlignment = eTextAlignment;

            drawingContext.DrawText( formattedText, new Point(dDrawX, dDrawY) );
        }
Example #26
0
        DrawSelfLoopAt
        (
            DrawingContext oDrawingContext,
            GraphDrawingContext oGraphDrawingContext,
            Color oColor,
            Double dWidth,
            Point oSelfLoopEndpoint,
            RectangleEdge eFarthestGraphRectangleEdge,
            Boolean bDrawArrow
        )
        {
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(dWidth >= 0);
            AssertValid();

            // The self-loop is drawn as a circle.  Figure out the location of the
            // circle's center and the tip of the arrow, if there is an arrow.

            Double dCircleX, dCircleY, dArrowTipX, dArrowTipY, dArrowAngle;

            dCircleX = dArrowTipX = oSelfLoopEndpoint.X;
            dCircleY = dArrowTipY = oSelfLoopEndpoint.Y;
            Double dSelfLoopCircleDiameter = 2.0 * SelfLoopCircleRadius;

            dArrowAngle = 0;

            switch (eFarthestGraphRectangleEdge)
            {
            case RectangleEdge.Top:

                dCircleY   -= SelfLoopCircleRadius;
                dArrowTipY -= dSelfLoopCircleDiameter;
                break;

            case RectangleEdge.Left:

                dCircleX   -= SelfLoopCircleRadius;
                dArrowTipX -= dSelfLoopCircleDiameter;
                dArrowAngle = Math.PI / 2.0;  // (90 degrees.)
                break;

            case RectangleEdge.Right:

                dCircleX   += SelfLoopCircleRadius;
                dArrowTipX += dSelfLoopCircleDiameter;
                dArrowAngle = -Math.PI / 2.0;  // (-90 degrees.)
                break;

            case RectangleEdge.Bottom:

                dCircleY   += SelfLoopCircleRadius;
                dArrowTipY += dSelfLoopCircleDiameter;
                dArrowAngle = Math.PI;  // (180 degrees.)
                break;

            default:

                Debug.Assert(false);
                break;
            }

            oDrawingContext.DrawEllipse(null, GetPen(oColor, dWidth),
                                        new Point(dCircleX, dCircleY), SelfLoopCircleRadius,
                                        SelfLoopCircleRadius);

            if (bDrawArrow)
            {
                // Rotate the arrow slightly to adjust to the circular shape of the
                // edge connected to it.

                dArrowAngle += Math.PI / 13.0;

                DrawArrow(oDrawingContext, new Point(dArrowTipX, dArrowTipY),
                          dArrowAngle, oColor, dWidth);
            }
        }
Example #27
0
        DrawLabel
        (
            DrawingContext drawingContext,
            GraphDrawingContext graphDrawingContext,
            VertexDrawingHistory vertexDrawingHistory,
            Rect vertexBounds,
            VertexLabelPosition labelPosition,
            FormattedText formattedText
        )
        {
            Debug.Assert(drawingContext != null);
            Debug.Assert(graphDrawingContext != null);
            Debug.Assert(vertexDrawingHistory != null);
            Debug.Assert(formattedText != null);
            AssertValid();

            Double        dHalfVertexBoundsWidth  = vertexBounds.Width / 2.0;
            Double        dHalfVertexBoundsHeight = vertexBounds.Height / 2.0;
            Double        dLabelHeight            = formattedText.Height;
            Double        dHalfLabelHeight        = dLabelHeight / 2.0;
            Double        dLabelWidth             = formattedText.Width;
            Double        dHalfLabelWidth         = dLabelWidth / 2.0;
            TextAlignment eTextAlignment          = TextAlignment.Left;

            formattedText.MaxLineCount = 1;

            // This is the point where the label will be drawn.  It initially
            // assumes a text height of zero with no margin, but that will be
            // adjusted within the switch statement below.

            Point  oDraw  = vertexDrawingHistory.GetLabelLocation(labelPosition);
            Double dDrawX = oDraw.X;
            Double dDrawY = oDraw.Y;

            // These are the bounds of the label text.

            Double dLabelBoundsLeft  = 0;
            Double dLabelBoundsRight = 0;

            switch (labelPosition)
            {
            case VertexLabelPosition.TopLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawY           -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft  = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.TopCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY           -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft  = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.TopRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawY           -= (dLabelHeight + VerticalMargin);
                dLabelBoundsLeft  = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            case VertexLabelPosition.MiddleLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawX           -= HorizontalMargin;
                dDrawY           -= dHalfLabelHeight;
                dLabelBoundsLeft  = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.MiddleCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY           -= dHalfLabelHeight;
                dLabelBoundsLeft  = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.MiddleRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawX           += HorizontalMargin;
                dDrawY           -= dHalfLabelHeight;
                dLabelBoundsLeft  = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            case VertexLabelPosition.BottomLeft:

                eTextAlignment = TextAlignment.Right;

                dDrawY           += VerticalMargin;
                dLabelBoundsLeft  = dDrawX - dLabelWidth;
                dLabelBoundsRight = dDrawX;

                break;

            case VertexLabelPosition.BottomCenter:

                eTextAlignment = TextAlignment.Center;

                dDrawY           += VerticalMargin;
                dLabelBoundsLeft  = dDrawX - dHalfLabelWidth;
                dLabelBoundsRight = dDrawX + dHalfLabelWidth;

                break;

            case VertexLabelPosition.BottomRight:

                // eTextAlignment = TextAlignment.Left;

                dDrawY           += VerticalMargin;
                dLabelBoundsLeft  = dDrawX;
                dLabelBoundsRight = dDrawX + dLabelWidth;

                break;

            default:

                Debug.Assert(false);
                break;
            }

            // Don't let the text exceed the bounds of the graph rectangle.

            Double dLabelBoundsTop    = dDrawY;
            Double dLabelBoundsBottom = dDrawY + dLabelHeight;

            Rect oGraphRectangleMinusMargin =
                graphDrawingContext.GraphRectangleMinusMargin;

            dDrawX += Math.Max(0,
                               oGraphRectangleMinusMargin.Left - dLabelBoundsLeft);

            dDrawX -= Math.Max(0,
                               dLabelBoundsRight - oGraphRectangleMinusMargin.Right);

            dDrawY += Math.Max(0,
                               oGraphRectangleMinusMargin.Top - dLabelBoundsTop);

            dDrawY -= Math.Max(0,
                               dLabelBoundsBottom - oGraphRectangleMinusMargin.Bottom);

            formattedText.TextAlignment = eTextAlignment;

            drawingContext.DrawText(formattedText, new Point(dDrawX, dDrawY));
        }
Example #28
0
        //*************************************************************************
        //  Method: DrawPlusSign()
        //
        /// <summary>
        /// Draws a plus sign on top of the vertex.
        /// </summary>
        ///
        /// <param name="eShape">
        /// The simple vertex shape.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="oVertexLocation">
        /// The location of the vertex.
        /// </param>
        ///
        /// <param name="oDrawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="oVertexColor">
        /// The color of the vertex.
        /// </param>
        ///
        /// <param name="oVertexLabelDrawer">
        /// Object that draws a vertex label as an annotation.
        /// </param>
        ///
        /// <param name="oVertexDrawingHistory">
        /// A <see cref="VertexDrawingHistory" /> object that retains information
        /// about how the vertex was drawn.
        /// </param>
        ///
        /// <param name="oVertexBounds">
        /// The rectangle defining the bounds of the vertex.
        /// </param>
        //*************************************************************************
        protected void DrawPlusSign(
            VertexShape eShape,
            Point oVertexLocation,
            Rect oVertexBounds,
            Color oVertexColor,
            GraphDrawingContext oGraphDrawingContext,
            DrawingContext oDrawingContext,
            VertexLabelDrawer oVertexLabelDrawer,
            VertexDrawingHistory oVertexDrawingHistory
            )
        {
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oVertexLabelDrawer != null);
            Debug.Assert(oVertexDrawingHistory != null);
            AssertValid();

            Color oFillColor;

            switch (eShape)
            {
            case VertexShape.Circle:
            case VertexShape.Square:
            case VertexShape.Diamond:
            case VertexShape.Triangle:

                // The fill color is the color of the background.  Adjust the
                // fill color for the opacity of the vertex.

                oFillColor = WpfGraphicsUtil.SetWpfColorAlpha(
                    oGraphDrawingContext.BackColor, oVertexColor.A);

                break;

            default:

                oFillColor = oVertexColor;
                break;
            }

            Color oContrastingColor =
            WpfGraphicsUtil.GetContrastingColor(oFillColor);

            // The font size used below was chosen so that it is large enough to be
            // easily readable, but small enough to fit within the smallest
            // collapsed group vertex created by the NodeXLControl.

            oVertexLabelDrawer.DrawLabel( oDrawingContext, oGraphDrawingContext,
            oVertexDrawingHistory, oVertexBounds,
            VertexLabelPosition.MiddleCenter,
            CreateFormattedText("+", oContrastingColor, 15.0) );
        }
Example #29
0
        DrawGraph
        (
            IGraph graph,
            GraphDrawingContext graphDrawingContext
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Implementation note:
            //
            // In a previous GDI+ implementation of this graph drawer, the edges
            // had to be drawn first to allow the vertices to cover the ends of the
            // edges.  That required a complex three-step drawing process: 1) allow
            // the vertex drawer to move each vertex if necessary to prevent the
            // vertex from falling outside the graph rectangle; 2) draw the edges
            // using the moved vertex locations; and 3) draw the vertices.
            //
            // This WPF implementation is simpler, for two reasons:
            //
            // 1. WPF uses retained-mode graphics, so covering the ends of the
            //    edges can be accomplished simply by adding
            //    m_oUnselectedEdgeDrawingVisuals to m_oVisualCollection before
            //    adding m_oAllVertexDrawingVisuals.  That means that the vertices
            //    can be drawn onto m_oAllVertexDrawingVisuals first, and the
            //    vertex drawer can move the vertices as necessary before drawing
            //    them.  A three-step process is no longer required.
            //
            // 2. The edges in this implementation don't actually need to be
            //    covered, because they terminate at the vertex boundaries instead
            //    of the vertex centers, as in the GDI+ implementation.

            m_oVisualCollection.Clear();

            DrawBackground(graph, graphDrawingContext);

            m_oAllVertexDrawingVisuals      = new DrawingVisual();
            m_oUnselectedEdgeDrawingVisuals = new DrawingVisual();
            m_oSelectedEdgeDrawingVisuals   = new DrawingVisual();

            // Draw the vertices after moving them if necessary.  Each vertex needs
            // to be individually hit-tested and possibly redrawn by
            // RedrawVertex(), so each vertex is put into its own DrawingVisual
            // that becomes a child of m_oAllVertexDrawingVisuals.

            foreach (IVertex oVertex in graph.Vertices)
            {
                DrawVertex(oVertex, graphDrawingContext);
            }

            // Draw the edges.  The edges don't need to be hit-tested, but they
            // might need to be redrawn by RedrawEdge(), so each edge is put into
            // its own DrawingVisual that becomes a child of either
            // m_oUnselectedEdgeDrawingVisuals or m_oSelectedEdgeDrawingVisuals.

            foreach (IEdge oEdge in graph.Edges)
            {
                DrawEdge(oEdge, graphDrawingContext);
            }

            // Selected edges need to be drawn on top of all the vertices
            // (including selected vertices) to guarantee that they will be
            // visible; hence the addition order seen here.

            m_oVisualCollection.Add(m_oUnselectedEdgeDrawingVisuals);
            m_oVisualCollection.Add(m_oAllVertexDrawingVisuals);
            m_oVisualCollection.Add(m_oSelectedEdgeDrawingVisuals);
        }
Example #30
0
        //*************************************************************************
        //  Method: DrawSimpleShape()
        //
        /// <summary>
        /// Draws a vertex as a simple shape.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex to draw.
        /// </param>
        ///
        /// <param name="eShape">
        /// The vertex shape to use.  Can't be <see cref="VertexShape.Image" /> or
        /// <see cref="VertexShape.Label" />.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="oDrawingContext">
        /// The DrawingContext to use.
        /// </param>
        ///
        /// <param name="oDrawingVisual">
        /// The <see cref="DrawingVisual" /> object from which <paramref
        /// name="oDrawingContext" /> was obtained.
        /// </param>
        ///
        /// <param name="eVisibility">
        /// The visibility of the vertex.
        /// </param>
        ///
        /// <param name="bDrawAsSelected">
        /// true to draw the vertex as selected.
        /// </param>
        ///
        /// <param name="sAnnotation">
        /// The annotation to draw next to the shape, or null if there is no
        /// annotation.
        /// </param>
        ///
        /// <param name="oVertexLabelDrawer">
        /// Object that draws a vertex label as an annotation.
        /// </param>
        ///
        /// <returns>
        /// A VertexDrawingHistory object that retains information about how the
        /// vertex was drawn.
        /// </returns>
        ///
        /// <remarks>
        /// "Simple" means "not <see cref="VertexShape.Image" /> and not <see
        /// cref="VertexShape.Label" />."
        /// </remarks>
        //*************************************************************************
        protected VertexDrawingHistory DrawSimpleShape(
            IVertex oVertex,
            VertexShape eShape,
            GraphDrawingContext oGraphDrawingContext,
            DrawingContext oDrawingContext,
            DrawingVisual oDrawingVisual,
            VisibilityKeyValue eVisibility,
            Boolean bDrawAsSelected,
            String sAnnotation,
            VertexLabelDrawer oVertexLabelDrawer
            )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            Debug.Assert(oDrawingContext != null);
            Debug.Assert(oDrawingVisual != null);
            Debug.Assert(oVertexLabelDrawer != null);
            AssertValid();

            Double dRadius = GetRadius(oVertex);
            Color oColor = GetColor(oVertex, eVisibility, bDrawAsSelected);
            Point oVertexLocation = GetVertexLocation(oVertex);

            Rect oVertexBounds;

            if (eShape == VertexShape.Triangle ||
            eShape == VertexShape.SolidTriangle)
            {
            oVertexBounds =
                WpfGraphicsUtil.TriangleBoundsFromCenterAndHalfWidth(
                    oVertexLocation, dRadius);
            }
            else
            {
            oVertexBounds = WpfGraphicsUtil.SquareFromCenterAndHalfWidth(
                oVertexLocation, dRadius);
            }

            // Move the vertex if it falls outside the graph rectangle.

            MoveVertexIfNecessary(oVertex, ref oVertexBounds,
            oGraphDrawingContext);

            Point oLocation = GetVertexLocation(oVertex);
            VertexDrawingHistory oVertexDrawingHistory = null;

            // Note that for the "hollow" shapes -- Circle, Square, Diamond, and
            // Triangle -- Brushes.Transparent is used instead of a null brush.
            // This allows the entire area of these shapes to be hit-tested.  Using
            // a null brush would cause hit-testing to fail if the shapes'
            // interiors were clicked.

            switch (eShape)
            {
            case VertexShape.Circle:
            case VertexShape.Disk:

                Boolean bIsDisk = (eShape == VertexShape.Disk);

                oDrawingContext.DrawEllipse(
                    bIsDisk ? GetBrush(oColor) : Brushes.Transparent,
                    bIsDisk ? null : GetPen(oColor, DefaultPenThickness),
                    oLocation, dRadius, dRadius
                    );

                oVertexDrawingHistory = bIsDisk ?

                    new DiskVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius)
                    :
                    new CircleVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius);

                break;

            case VertexShape.Sphere:

                RadialGradientBrush oRadialGradientBrush =
                    new RadialGradientBrush();

                oRadialGradientBrush.GradientOrigin =
                    oRadialGradientBrush.Center = new Point(0.3, 0.3);

                GradientStopCollection oGradientStops =
                    oRadialGradientBrush.GradientStops;

                oGradientStops.Add( new GradientStop(Colors.White, 0.0) );
                oGradientStops.Add( new GradientStop(oColor, 1.0) );

                WpfGraphicsUtil.FreezeIfFreezable(oRadialGradientBrush);

                oDrawingContext.DrawEllipse(oRadialGradientBrush, null,
                    oLocation, dRadius, dRadius);

                oVertexDrawingHistory = new SphereVertexDrawingHistory(
                    oVertex, oDrawingVisual, bDrawAsSelected, dRadius);

                break;

            case VertexShape.Square:
            case VertexShape.SolidSquare:

                Boolean bIsSolidSquare = (eShape == VertexShape.SolidSquare);

                oDrawingContext.DrawRectangle(
                    bIsSolidSquare ? GetBrush(oColor) : Brushes.Transparent,
                    bIsSolidSquare? null : GetPen(oColor, DefaultPenThickness),
                    oVertexBounds
                    );

                oVertexDrawingHistory = bIsSolidSquare ?

                    new SolidSquareVertexDrawingHistory(oVertex,
                        oDrawingVisual, bDrawAsSelected, oVertexBounds)
                    :
                    new SquareVertexDrawingHistory(oVertex,
                        oDrawingVisual, bDrawAsSelected, oVertexBounds);

                break;

            case VertexShape.Diamond:
            case VertexShape.SolidDiamond:

                Boolean bIsSolidDiamond = (eShape == VertexShape.SolidDiamond);

                PathGeometry oDiamond =
                    WpfGraphicsUtil.DiamondFromCenterAndHalfWidth(
                        oLocation, dRadius);

                oDrawingContext.DrawGeometry(

                    bIsSolidDiamond ? GetBrush(oColor) : Brushes.Transparent,

                    bIsSolidDiamond ? null :
                        GetPen(oColor, DefaultPenThickness),

                    oDiamond
                    );

                oVertexDrawingHistory = bIsSolidDiamond ?

                    new SolidDiamondVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius)
                    :
                    new DiamondVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius);

                break;

            case VertexShape.Triangle:
            case VertexShape.SolidTriangle:

                Boolean bIsSolidTriangle =
                    (eShape == VertexShape.SolidTriangle);

                PathGeometry oTriangle =
                    WpfGraphicsUtil.TriangleFromCenterAndHalfWidth(
                        oLocation, dRadius);

                oDrawingContext.DrawGeometry(

                    bIsSolidTriangle ? GetBrush(oColor) : Brushes.Transparent,

                    bIsSolidTriangle ? null :
                        GetPen(oColor, DefaultPenThickness),

                    oTriangle
                    );

                oVertexDrawingHistory = bIsSolidTriangle ?

                    new SolidTriangleVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius)
                    :
                    new TriangleVertexDrawingHistory(
                        oVertex, oDrawingVisual, bDrawAsSelected, dRadius);

                break;

            default:

                Debug.Assert(false);
                break;
            }

            if (sAnnotation != null)
            {
            oVertexLabelDrawer.DrawLabel( oDrawingContext,
                oGraphDrawingContext, oVertexDrawingHistory, oVertexBounds,
                CreateFormattedText(sAnnotation, oColor) );
            }

            if ( oVertex.ContainsKey(ReservedMetadataKeys.PerVertexDrawPlusSign) )
            {
            DrawPlusSign(eShape, oVertexLocation, oVertexBounds, oColor,
                oGraphDrawingContext, oDrawingContext, oVertexLabelDrawer,
                oVertexDrawingHistory);
            }

            Debug.Assert(oVertexDrawingHistory != null);

            return (oVertexDrawingHistory);
        }
Example #31
0
        //*************************************************************************
        //  Method: DrawVertex()
        //
        /// <summary>
        /// Draws a vertex onto the contained collection of Visual objects.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex to draw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <remarks>
        /// This method adds a DrawingVisual for the vertex to
        /// m_oAllVertexDrawingVisuals and adds a VertexDrawingHistory to
        /// oGraphDrawingContext.VertexDrawingHistories.
        /// </remarks>
        //*************************************************************************
        protected void DrawVertex(
            IVertex oVertex,
            GraphDrawingContext oGraphDrawingContext
            )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            VertexDrawingHistory oVertexDrawingHistory;

            Dictionary<Int32, VertexDrawingHistory> oVertexDrawingHistories =
            oGraphDrawingContext.VertexDrawingHistories;

            if ( m_oVertexDrawer.TryDrawVertex(oVertex, oGraphDrawingContext,
            out oVertexDrawingHistory) )
            {
            Debug.Assert(oVertexDrawingHistory != null);

            // Add the DrawingVisual for the vertex to
            // m_oAllVertexDrawingVisuals, and add the VertexDrawingHistory to
            // the oGraphDrawingContext.VertexDrawingHistories dictionary.

            DrawingVisual oVertexChildDrawingVisual =
                oVertexDrawingHistory.DrawingVisual;

            m_oAllVertexDrawingVisuals.Children.Add(oVertexChildDrawingVisual);

            oVertexDrawingHistories.Add(oVertex.ID, oVertexDrawingHistory);

            // Save the vertex on the DrawingVisual for later retrieval.

            SaveVertexOnDrawingVisual(oVertex, oVertexChildDrawingVisual);
            }
        }
Example #32
0
        //*************************************************************************
        //  Method: MoveVertexIfNecessary()
        //
        /// <summary>
        /// Moves a vertex if it falls within the graph rectangle's margin or
        /// outside the graph rectangle.
        /// </summary>
        ///
        /// <param name="oVertex">
        /// The vertex to move.
        /// </param>
        ///
        /// <param name="oVertexBounds">
        /// The rectangle defining the bounds of the vertex.  This gets updated if
        /// the vertex is moved.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <remarks>
        /// If the vertex falls within the margin or outside the graph rectangle,
        /// the IVertex.Location property and <paramref name="oVertexBounds" /> get
        /// updated.
        /// </remarks>
        //*************************************************************************
        protected void MoveVertexIfNecessary(
            IVertex oVertex,
            ref Rect oVertexBounds,
            GraphDrawingContext oGraphDrawingContext
            )
        {
            Debug.Assert(oVertex != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            if (!m_bLimitVerticesToBounds)
            {
            // The vertex shouldn't be moved.

            return;
            }

            Rect oGraphRectangleMinusMargin =
            oGraphDrawingContext.GraphRectangleMinusMargin;

            if (oGraphRectangleMinusMargin.IsEmpty)
            {
            return;
            }

            Rect oMovedVertexBounds = WpfGraphicsUtil.MoveRectangleWithinBounds(
            oVertexBounds, oGraphRectangleMinusMargin, false);

            oVertex.Location = System.Drawing.PointF.Add( oVertex.Location,
            new System.Drawing.SizeF(
                (Single)(oMovedVertexBounds.X - oVertexBounds.X),
                (Single)(oMovedVertexBounds.Y - oVertexBounds.Y)
                ) );

            oVertexBounds = oMovedVertexBounds;
        }
Example #33
0
        //*************************************************************************
        //  Method: DrawNewEdge()
        //
        /// <summary>
        /// Draws an edge that has been added to the graph but not yet drawn by
        /// <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="newEdge">
        /// The new edge to draw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to draw a new edge without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void DrawNewEdge(
            IEdge newEdge,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(newEdge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            DrawEdge(newEdge, graphDrawingContext);
        }
Example #34
0
        //*************************************************************************
        //  Method: TryDrawVertex()
        //
        /// <summary>
        /// Draws a vertex after moving it if necessary.
        /// </summary>
        ///
        /// <param name="vertex">
        /// The vertex to draw.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        ///
        /// <param name="vertexDrawingHistory">
        /// Where a <see cref="VertexDrawingHistory" /> object that retains
        /// information about how the vertex was drawn gets stored if true is
        /// returned.
        /// </param>
        ///
        /// <returns>
        /// true if the vertex was drawn, false if the vertex is hidden.
        /// </returns>
        ///
        /// <remarks>
        /// This method should be called repeatedly while a graph is being drawn,
        /// once for each of the graph's vertices.  The <see
        /// cref="IVertex.Location" /> property on all of the graph's vertices must
        /// be set by ILayout.LayOutGraph before this method is called.
        ///
        /// <para>
        /// If the vertex falls outside the graph rectangle, it gets moved before
        /// being drawn.
        /// </para>
        ///
        /// </remarks>
        //*************************************************************************
        public Boolean TryDrawVertex(
            IVertex vertex,
            GraphDrawingContext graphDrawingContext,
            out VertexDrawingHistory vertexDrawingHistory
            )
        {
            AssertValid();

            vertexDrawingHistory = null;

            CheckDrawVertexArguments(vertex, graphDrawingContext);

            // If the vertex is hidden, do nothing.

            VisibilityKeyValue eVisibility = GetVisibility(vertex);

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

            // Check for a per-vertex label.

            Object oLabelAsObject;
            String sLabel = null;

            if ( vertex.TryGetValue(ReservedMetadataKeys.PerVertexLabel,
            typeof(String), out oLabelAsObject) )
            {
            sLabel = (String)oLabelAsObject;

            if ( String.IsNullOrEmpty(sLabel) )
            {
                sLabel = null;
            }
            else
            {
                sLabel = TruncateLabel(sLabel);
            }
            }

            Boolean bDrawAsSelected = GetDrawAsSelected(vertex);
            Point oLocation = WpfGraphicsUtil.PointFToWpfPoint(vertex.Location);
            DrawingVisual oDrawingVisual = new DrawingVisual();
            VertexShape eShape = GetShape(vertex);

            VertexLabelDrawer oVertexLabelDrawer =
            new VertexLabelDrawer(m_eLabelPosition);

            using ( DrawingContext oDrawingContext = oDrawingVisual.RenderOpen() )
            {
            if (eShape == VertexShape.Label)
            {
                if (sLabel != null)
                {
                    // Draw the vertex as a label.

                    vertexDrawingHistory = DrawLabelShape(vertex,
                        graphDrawingContext, oDrawingContext, oDrawingVisual,
                        eVisibility, bDrawAsSelected, sLabel);

                    return (true);
                }

                // Default to something usable.

                eShape = VertexShape.Disk;
            }
            else if (eShape == VertexShape.Image)
            {
                Object oImageSourceAsObject;

                if (vertex.TryGetValue(ReservedMetadataKeys.PerVertexImage,
                    typeof(ImageSource), out oImageSourceAsObject)
                    )
                {
                    // Draw the vertex as an image.

                    vertexDrawingHistory = DrawImageShape(vertex,
                        graphDrawingContext, oDrawingContext, oDrawingVisual,
                        eVisibility, bDrawAsSelected, sLabel,
                        (ImageSource)oImageSourceAsObject, oVertexLabelDrawer);

                    return (true);
                }

                // Default to something usable.

                eShape = VertexShape.Disk;
            }

            // Draw the vertex as a simple shape.

            vertexDrawingHistory = DrawSimpleShape(vertex, eShape,
                graphDrawingContext, oDrawingContext, oDrawingVisual,
                eVisibility, bDrawAsSelected, sLabel, oVertexLabelDrawer);
            }

            return (true);
        }
Example #35
0
        //*************************************************************************
        //  Method: RedrawEdge()
        //
        /// <summary>
        /// Redraws an edge that was drawn by <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="edge">
        /// The edge to redraw onto the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to redraw an edge whose attributes (such as its
        /// selected state) have changed without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void RedrawEdge(
            IEdge edge,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            UndrawEdge(edge, graphDrawingContext);
            DrawEdge(edge, graphDrawingContext);
        }
Example #36
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 #37
0
        //*************************************************************************
        //  Method: UndrawEdge()
        //
        /// <summary>
        /// "Undraws" an edge that was drawn by <see cref="DrawGraph" />.
        /// </summary>
        ///
        /// <param name="edge">
        /// The edge to remove from the contained collection of Visual objects.
        /// </param>
        ///
        /// <param name="graphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.  This
        /// must be the same object that was passed to <see cref="DrawGraph" /> the
        /// last time the entire graph was drawn.
        /// </param>
        ///
        /// <remarks>
        /// Use this method to undraw an edge without incurring the overhead of
        /// redrawing the entire graph.
        /// </remarks>
        //*************************************************************************
        public void UndrawEdge(
            IEdge edge,
            GraphDrawingContext graphDrawingContext
            )
        {
            Debug.Assert(edge != null);
            Debug.Assert(graphDrawingContext != null);
            AssertValid();

            // Retrieve the EdgeDrawingHistory object for the edge, if one exists.
            // (If the edge was previously hidden, there won't be an
            // EdgeDrawingHistory object for it.)

            Dictionary<Int32, EdgeDrawingHistory> oEdgeDrawingHistories =
            graphDrawingContext.EdgeDrawingHistories;

            Int32 iEdgeID = edge.ID;
            EdgeDrawingHistory oEdgeDrawingHistory;

            if ( oEdgeDrawingHistories.TryGetValue(
            iEdgeID, out oEdgeDrawingHistory) )
            {
            // Remove the EdgeDrawingHistory object from the dictionary.

            oEdgeDrawingHistories.Remove(iEdgeID);

            // Remove the edge's DrawingVisual object, which will cause the
            // edge to disappear.

            GetEdgeDrawingVisuals(oEdgeDrawingHistory).Children.Remove(
                oEdgeDrawingHistory.DrawingVisual);
            }
        }
Example #38
0
        //*************************************************************************
        //  Method: DrawGraph()
        //
        /// <summary>
        /// Draws the graph.
        /// </summary>
        ///
        /// <param name="oGraphRectangle">
        /// Rectangle to draw the graph within.
        /// </param>
        //*************************************************************************
        protected void DrawGraph(
            Rect oGraphRectangle
            )
        {
            AssertValid();

            #if TRACE_LAYOUT_AND_DRAW
            Debug.WriteLine("NodeXLControl: DrawGraph(), oGraphRectangle = "
            + oGraphRectangle);
            #endif

            m_oLastGraphDrawingContext = new GraphDrawingContext(
            oGraphRectangle, m_oAsyncLayout.Margin, m_oGraphDrawer.BackColor);

            m_oGraphDrawer.DrawGraph(m_oGraph, m_oLastGraphDrawingContext);
        }
Example #39
0
        //*************************************************************************
        //  Method: DrawBackground()
        //
        /// <summary>
        /// Draws the graph's background.
        /// </summary>
        ///
        /// <param name="oGraph">
        /// The graph being drawn.
        /// </param>
        ///
        /// <param name="oGraphDrawingContext">
        /// Provides access to objects needed for graph-drawing operations.
        /// </param>
        //*************************************************************************
        protected void DrawBackground(
            IGraph oGraph,
            GraphDrawingContext oGraphDrawingContext
            )
        {
            Debug.Assert(oGraph != null);
            Debug.Assert(oGraphDrawingContext != null);
            AssertValid();

            // Draw the background color, followed by the background image if one
            // was specified.

            Color oBackColor;

            if ( !TryGetColorValue(oGraph, ReservedMetadataKeys.GraphBackColor,
            out oBackColor) )
            {
            oBackColor = m_oBackColor;
            }

            DrawingVisual oBackgroundDrawingVisual = new DrawingVisual();

            using ( DrawingContext oDrawingContext =
            oBackgroundDrawingVisual.RenderOpen() )
            {
            oDrawingContext.DrawRectangle(
                CreateFrozenSolidColorBrush(oBackColor), null,
                oGraphDrawingContext.GraphRectangle);

            Object oImageSourceAsObject;

            if ( oGraph.TryGetValue(ReservedMetadataKeys.GraphBackgroundImage,
                typeof(ImageSource), out oImageSourceAsObject) )
            {
                ImageSource oImageSource = (ImageSource)oImageSourceAsObject;

                oDrawingContext.DrawImage( oImageSource,
                    new Rect( new Size(oImageSource.Width,
                        oImageSource.Height) ) );
            }
            }

            m_oVisualCollection.Add(oBackgroundDrawingVisual);
        }
Example #40
0
        //*************************************************************************
        //  Constructor: NodeXLControl()
        //
        /// <summary>
        /// Initializes a new instance of the <see cref="NodeXLControl" /> class.
        /// </summary>
        //*************************************************************************
        public NodeXLControl()
        {
            m_oGraph = new Graph();
            m_oGraphDrawer = new GraphDrawer(this);

            m_oAsyncLayout = new FruchtermanReingoldLayout();
            OnNewLayout(m_oAsyncLayout);

            m_oLastLayoutContext =
            new LayoutContext(System.Drawing.Rectangle.Empty);

            m_oLastGraphDrawingContext = null;

            m_eLayoutState = LayoutState.Stable;

            m_eMouseMode = MouseMode.Select;
            m_bMouseAlsoSelectsIncidentEdges = true;
            m_bAllowVertexDrag = true;

            m_oVerticesBeingDragged = null;
            m_oMarqueeBeingDragged = null;
            m_oTranslationBeingDragged = null;

            m_oSelectedVertices = new HashSet<IVertex>();
            m_oSelectedEdges = new HashSet<IEdge>();
            m_oCollapsedGroups = new Dictionary<String, IVertex>();
            m_oDoubleClickedVertexInfo = null;

            m_bShowVertexToolTips = false;
            m_oLastMouseMoveLocation = new Point(-1, -1);

            // Create a helper object for displaying vertex tooltips.

            CreateVertexToolTipTracker();
            m_oVertexToolTip = null;

            m_bGraphZoomCentered = false;

            this.AddLogicalChild(m_oGraphDrawer.VisualCollection);

            CreateTransforms();

            // Prevent a focus rectangle from being drawn around the control when
            // it captures keyboard focus.  The focus rectangle does not behave
            // properly when the layout and render transforms are applied --
            // sometimes the rectangle disappears, and sometimes it gets magnified
            // by the render layout.

            this.FocusVisualStyle = null;

            // AssertValid();
        }