PostDrawVertex ( VertexShape vertexShape, Color vertexColor, GraphDrawingContext graphDrawingContext, DrawingContext drawingContext, Boolean drawAsSelected, Double graphScale, VertexLabelDrawer vertexLabelDrawer, FormattedTextManager formattedTextManager, VertexDrawingHistory vertexDrawingHistory ) { Debug.Assert(graphDrawingContext != null); Debug.Assert(drawingContext != null); Debug.Assert(graphScale >= GraphDrawer.MinimumGraphScale); Debug.Assert(graphScale <= GraphDrawer.MaximumGraphScale); Debug.Assert(vertexLabelDrawer != null); Debug.Assert(formattedTextManager != null); Debug.Assert(vertexDrawingHistory != null); AssertValid(); if (m_oCollapsedGroupVertex == null) { // The vertex that was drawn is not a collapsed group vertex. Do // nothing. return; } if (m_oCollapsedGroupAttributes.Count == 0) { // The vertex that was drawn represents a collapsed group, but no // attributes were specified for it. By default, such a vertex // gets a plus sign drawn on top of it. DrawPlusSign(vertexShape, vertexColor, graphDrawingContext, drawingContext, graphScale, vertexLabelDrawer, formattedTextManager, vertexDrawingHistory); } else { // Check whether this this is a collapsed motif. switch ( m_oCollapsedGroupAttributes.GetGroupType() ) { case CollapsedGroupAttributeValues.FanMotifType: DrawFanMotifFan(vertexColor, drawingContext, drawAsSelected, graphScale, vertexDrawingHistory); break; default: // Do nothing. This includes the D-connector motif case, // which requires no post-drawing action. break; } } }
DrawPlusSign ( VertexShape eVertexShape, Color oVertexColor, GraphDrawingContext oGraphDrawingContext, DrawingContext oDrawingContext, Double dGraphScale, VertexLabelDrawer oVertexLabelDrawer, FormattedTextManager oFormattedTextManager, VertexDrawingHistory oVertexDrawingHistory ) { Debug.Assert(oGraphDrawingContext != null); Debug.Assert(oDrawingContext != null); Debug.Assert(dGraphScale >= GraphDrawer.MinimumGraphScale); Debug.Assert(dGraphScale <= GraphDrawer.MaximumGraphScale); Debug.Assert(oVertexLabelDrawer != null); Debug.Assert(oFormattedTextManager != null); Debug.Assert(oVertexDrawingHistory != null); AssertValid(); Color oFillColor; switch (eVertexShape) { 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 this class. oVertexLabelDrawer.DrawLabel(oDrawingContext, oGraphDrawingContext, oVertexDrawingHistory, VertexLabelPosition.MiddleCenter, oFormattedTextManager.CreateFormattedText("+", oContrastingColor, 15.0, dGraphScale), oContrastingColor, false); }
TryDrawVertex ( IVertex vertex, GraphDrawingContext graphDrawingContext, out VertexDrawingHistory vertexDrawingHistory ) { AssertValid(); vertexDrawingHistory = null; CheckDrawVertexArguments(vertex, graphDrawingContext); if (graphDrawingContext.GraphRectangleMinusMarginIsEmpty) { return (false); } // If the vertex is hidden, do nothing. VisibilityKeyValue eVisibility = GetVisibility(vertex); if (eVisibility == VisibilityKeyValue.Hidden) { return (false); } // Check whether the vertex represents a collapsed group and perform // collapsed group tasks if necessary. CollapsedGroupDrawingManager oCollapsedGroupDrawingManager = new CollapsedGroupDrawingManager(); oCollapsedGroupDrawingManager.PreDrawVertex(vertex); // 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); DrawingVisualPlus oDrawingVisual = new DrawingVisualPlus(); VertexShape eShape = GetShape(vertex); VertexLabelDrawer oVertexLabelDrawer = new VertexLabelDrawer(m_eLabelPosition, m_btBackgroundAlpha); 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, oCollapsedGroupDrawingManager); } else { // 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, oCollapsedGroupDrawingManager); } else { // Default to something usable. eShape = VertexShape.Disk; } } if (vertexDrawingHistory == null) { // Draw the vertex as a simple shape. vertexDrawingHistory = DrawSimpleShape(vertex, eShape, graphDrawingContext, oDrawingContext, oDrawingVisual, eVisibility, bDrawAsSelected, sLabel, oVertexLabelDrawer, oCollapsedGroupDrawingManager); } // Perform collapsed group tasks if necessary. oCollapsedGroupDrawingManager.PostDrawVertex(eShape, GetColor(vertex, eVisibility, bDrawAsSelected), graphDrawingContext, oDrawingContext, bDrawAsSelected, m_dGraphScale, oVertexLabelDrawer, m_oFormattedTextManager, vertexDrawingHistory); } return (true); }
DrawSimpleShape ( IVertex oVertex, VertexShape eShape, GraphDrawingContext oGraphDrawingContext, DrawingContext oDrawingContext, DrawingVisualPlus oDrawingVisual, VisibilityKeyValue eVisibility, Boolean bDrawAsSelected, String sAnnotation, VertexLabelDrawer oVertexLabelDrawer, CollapsedGroupDrawingManager oCollapsedGroupDrawingManager ) { Debug.Assert(oVertex != null); Debug.Assert(oGraphDrawingContext != null); Debug.Assert(oDrawingContext != null); Debug.Assert(oDrawingVisual != null); Debug.Assert(oVertexLabelDrawer != null); Debug.Assert(oCollapsedGroupDrawingManager != null); AssertValid(); Double dRadius = GetRadius(oVertex); Color oColor = GetColor(oVertex, eVisibility, bDrawAsSelected); Point oVertexLocation = GetVertexLocation(oVertex); oDrawingVisual.SetEffect( GetSimpleShapeEffect( oGraphDrawingContext, dRadius, oColor) ); Rect oVertexBounds; if (eShape == VertexShape.Triangle || eShape == VertexShape.SolidTriangle) { oVertexBounds = WpfGraphicsUtil.TriangleBoundsFromCenterAndHalfWidth( oVertexLocation, dRadius); } else if (eShape == VertexShape.SolidTaperedDiamond) { // Note that the bounds of a tapered diamond can't be calculated // using simple equations. Instead, create the tapered diamond and // let WPF compute the bounds. // // There is some inefficiency here, because the tapered diamond // gets created again before it is drawn, in its possibly-moved // location. oVertexBounds = WpfPathGeometryUtil.GetTaperedDiamond( oVertexLocation, dRadius).Bounds; } else if (eShape == VertexShape.SolidRoundedX) { // Note that the bounds of a rounded X can't be calculated // using simple equations. Instead, create the rounded X and // let WPF compute the bounds. // // There is some inefficiency here, because the rounded X // gets created again before it is drawn, in its possibly-moved // location. oVertexBounds = WpfPathGeometryUtil.GetRoundedX( oVertexLocation, dRadius).Bounds; } else { oVertexBounds = WpfGraphicsUtil.SquareFromCenterAndHalfWidth( oVertexLocation, dRadius); } // Move the vertex if it falls outside the graph rectangle. MoveVertexIfNecessary(oVertex, oGraphDrawingContext, oCollapsedGroupDrawingManager, ref oVertexBounds); oVertexLocation = 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), oVertexLocation, 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( WpfGraphicsUtil.SetWpfColorAlpha(Colors.White, oColor.A), 0.0) ); oGradientStops.Add( new GradientStop(oColor, 1.0) ); WpfGraphicsUtil.FreezeIfFreezable(oRadialGradientBrush); oDrawingContext.DrawEllipse(oRadialGradientBrush, null, oVertexLocation, dRadius, dRadius); oVertexDrawingHistory = new SphereVertexDrawingHistory( oVertex, oDrawingVisual, bDrawAsSelected, dRadius); break; case VertexShape.Square: WpfGraphicsUtil.DrawPixelAlignedRectangle(oDrawingContext, Brushes.Transparent, GetPen(oColor, DefaultPenThickness), oVertexBounds); oVertexDrawingHistory = new SquareVertexDrawingHistory(oVertex, oDrawingVisual, bDrawAsSelected, oVertexBounds); break; case VertexShape.SolidSquare: oDrawingContext.DrawRectangle(GetBrush(oColor), null, oVertexBounds); oVertexDrawingHistory = new SolidSquareVertexDrawingHistory( oVertex, oDrawingVisual, bDrawAsSelected, oVertexBounds); break; case VertexShape.Diamond: case VertexShape.SolidDiamond: Boolean bIsSolidDiamond = (eShape == VertexShape.SolidDiamond); PathGeometry oDiamond = WpfPathGeometryUtil.GetDiamond(oVertexLocation, 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 = WpfPathGeometryUtil.GetTriangle(oVertexLocation, 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; case VertexShape.SolidTaperedDiamond: Geometry oTaperedDiamond = WpfPathGeometryUtil.GetTaperedDiamond( oVertexLocation, dRadius); // Note that as of August 2012, the tapered diamond shape is // used only for collapsed connector motifs. Collapsed motifs // have an outline, so draw an outline here. oDrawingContext.DrawGeometry(GetBrush(oColor), GetPen( CollapsedGroupDrawingManager .GetCollapsedMotifOutlineColor(oColor.A), DefaultPenThickness), oTaperedDiamond); oVertexDrawingHistory = new SolidTaperedDiamondVertexDrawingHistory( oVertex, oDrawingVisual, bDrawAsSelected, dRadius); break; case VertexShape.SolidRoundedX: Geometry oRoundedX = WpfPathGeometryUtil.GetRoundedX( oVertexLocation, dRadius); // Note that as of August 2012, the rounded X shape is // used only for collapsed clique motifs. Collapsed motifs // have an outline, so draw an outline here. oDrawingContext.DrawGeometry(GetBrush(oColor), GetPen(CollapsedGroupDrawingManager .GetCollapsedMotifOutlineColor(oColor.A), DefaultPenThickness), oRoundedX); oVertexDrawingHistory = new SolidRoundedXVertexDrawingHistory( oVertex, oDrawingVisual, bDrawAsSelected, dRadius); break; default: Debug.Assert(false); break; } if (sAnnotation != null) { oVertexLabelDrawer.DrawLabel(oDrawingContext, oGraphDrawingContext, oVertexDrawingHistory, CreateFormattedTextWithWrap(sAnnotation, oColor, m_oFormattedTextManager.FontSize), oColor); } Debug.Assert(oVertexDrawingHistory != null); return (oVertexDrawingHistory); }
DrawImageShape ( IVertex oVertex, GraphDrawingContext oGraphDrawingContext, DrawingContext oDrawingContext, DrawingVisualPlus oDrawingVisual, VisibilityKeyValue eVisibility, Boolean bDrawAsSelected, String sAnnotation, ImageSource oImageSource, VertexLabelDrawer oVertexLabelDrawer, CollapsedGroupDrawingManager oCollapsedGroupDrawingManager ) { Debug.Assert(oVertex != null); Debug.Assert(oGraphDrawingContext != null); Debug.Assert(oDrawingContext != null); Debug.Assert(oDrawingVisual != null); Debug.Assert(oImageSource != null); Debug.Assert(oVertexLabelDrawer != null); Debug.Assert(oCollapsedGroupDrawingManager != 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, oGraphDrawingContext, oCollapsedGroupDrawingManager, ref oVertexRectangle); 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); oDrawingVisual.SetEffect( GetRectangleEffect( oGraphDrawingContext, oColor) ); // Draw an outline rectangle. WpfGraphicsUtil.DrawPixelAlignedRectangle(oDrawingContext, 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, CreateFormattedTextWithWrap(sAnnotation, oColor, m_oFormattedTextManager.FontSize), oColor ); } } return (oVertexDrawingHistory); }