/// <summary> /// Initialize paint settings. This is initialized after the base shape /// has been painted. /// </summary> public PaintHelper(DiagramPaintEventArgs e, ExternalConstraintShape constraintShape) { StyleSet styleSet = constraintShape.StyleSet; StyleSetResourceId penId = constraintShape.OutlinePenId; Pen pen = styleSet.GetPen(penId); Brush brush = styleSet.GetBrush(ExternalConstraintBrush); SolidBrush coloredBrush = brush as SolidBrush; // Keep the pen color in sync with the color being used for highlighting Color startColor = constraintShape.UpdateDynamicColor(constraintShape.OutlinePenId, pen); if (startColor.IsEmpty) { startColor = constraintShape.UpdateGeometryLuminosity(e.View, pen); } else { constraintShape.UpdateGeometryLuminosity(e.View, pen); } myPenStartColor = startColor; Color newColor = pen.Color; if (coloredBrush != null) { myBrushStartColor = coloredBrush.Color; coloredBrush.Color = newColor; } else { myBrushStartColor = Color.Empty; } myBrush = brush; myPen = pen; }
/// <summary> /// Replacement for <see cref="ShapeField.GetBackgroundBrush"/> that recognizes /// <see cref="IDynamicColorGeometryHost"/> /// </summary> public override Pen GetPen(DiagramClientView view, ShapeElement parentShape, ref Color oldColor) { StyleSet styleSet = (parentShape != null) ? parentShape.StyleSet : null; Color restoreColor = Color.Empty; Pen pen = null; if (styleSet != null) { StyleSetResourceId penId = GetPenId(parentShape); pen = styleSet.GetPen(penId); IDynamicColorGeometryHost dynamicColors = parentShape as IDynamicColorGeometryHost; if (dynamicColors == null || (restoreColor = dynamicColors.UpdateDynamicColor(penId, pen)).IsEmpty) { if (view != null) { restoreColor = parentShape.UpdateGeometryLuminosity(view, pen); } } else if (view != null) { parentShape.UpdateGeometryLuminosity(view, pen); } } if (pen != null && !restoreColor.IsEmpty) { restoreColor = pen.Color; } return(pen); }
/// <summary> /// Paint the shape contents based on the operator type. /// </summary> protected override void OnPaintShape(DiagramPaintEventArgs e, ref PaintHelper helper) { base.OnPaintShape(e, ref helper); ValueComparisonConstraint comparisonConstraint = this.AssociatedValueComparisonConstraint; RectangleD bounds = this.AbsoluteBounds; RectangleF boundsF = RectangleD.ToRectangleF(bounds); Graphics g = e.Graphics; ValueComparisonOperator comparisonOperator = comparisonConstraint.Operator; Brush brush = helper.Brush; // Draw the left and right comparison dots float heightF = boundsF.Height; float dotDiameter = heightF * DOT_FACTOR; float dotRadius = dotDiameter / 2; float dotTop = boundsF.Top + heightF / 2 - dotRadius; g.FillEllipse(brush, boundsF.Left - dotRadius, dotTop, dotDiameter, dotDiameter); g.FillEllipse(brush, boundsF.Right - dotRadius, dotTop, dotDiameter, dotDiameter); if (comparisonOperator != ValueComparisonOperator.Undefined) // Undefined just draws the error state { // Draw the operator using a different pen. Pen pen = StyleSet.GetPen(OperatorResource); // Get the correct pen color from the provided outline pen Color startColor = pen.Color; Color shapeColor = helper.Pen.Color; // The paint helper has already updated the color, just use it. bool updateColor; if (updateColor = (startColor != shapeColor)) { pen.Color = shapeColor; } // Get a clipping rectangle we can draw inside of. This // gives us a nice vertical clip on the open side of the // comparator, as well as a region safely inside the shape // outline. const double inscribedRectAngle = 1d / 3 * Math.PI; // 60 degrees from center point of shape to shape border. const float equalsOffsetFactor = .8f; const double noEqualityPiDivisor = 6d; // 30 degree angle on comparator line const double withEqualityPiDivisor = 7.5d; // 24 degree angle on comparator line double inscribedCos = Math.Cos(inscribedRectAngle); double inscribedSin = Math.Sin(inscribedRectAngle); double width = bounds.Width; double height = bounds.Height; bounds = new RectangleD( bounds.Left + (1 - inscribedCos) * width / 2, bounds.Top + (1 - inscribedSin) * height / 2, inscribedCos * width, inscribedSin * height); //width = bounds.Width; // not used below height = bounds.Height; boundsF = RectangleD.ToRectangleF(bounds); bool drawComparator = true; bool drawEquality = false; bool slashEquality = false; float penWidth = pen.Width; float openSideX = 0f; float closedSideX = 0f; switch (comparisonOperator) { case ValueComparisonOperator.LessThanOrEqual: drawEquality = true; goto case ValueComparisonOperator.LessThan; case ValueComparisonOperator.LessThan: openSideX = boundsF.Right; closedSideX = boundsF.Left + penWidth / 2; break; case ValueComparisonOperator.GreaterThanOrEqual: drawEquality = true; goto case ValueComparisonOperator.GreaterThan; case ValueComparisonOperator.GreaterThan: openSideX = boundsF.Left; closedSideX = boundsF.Right - penWidth / 2; break; case ValueComparisonOperator.Equal: drawComparator = false; drawEquality = true; break; case ValueComparisonOperator.NotEqual: drawComparator = false; drawEquality = true; slashEquality = true; break; } double halfHeight = height / 2; double top = bounds.Top; float middle = (float)(top + halfHeight); float topTip; float bottomTip; if (drawComparator) { g.SetClip(boundsF); // Use a path so that we get a clean join between the top and bottom lines. float equalsOffset = drawEquality ? penWidth * equalsOffsetFactor : 0f; double offsetSin = Math.Sin(Math.PI / (drawEquality ? withEqualityPiDivisor : noEqualityPiDivisor)); topTip = (float)(top + halfHeight * (1d - offsetSin)); bottomTip = (float)(top + halfHeight * (1d + offsetSin)); using (GraphicsPath path = new GraphicsPath()) { path.AddLines(new PointF[] { new PointF(openSideX, topTip - equalsOffset), new PointF(closedSideX, middle - equalsOffset), new PointF(openSideX, bottomTip - equalsOffset) }); g.DrawPath(pen, path); } if (drawEquality) { bottomTip += equalsOffset; g.DrawLine( pen, boundsF.Left, bottomTip, boundsF.Right, bottomTip); } } else if (drawEquality) { g.SetClip(boundsF); openSideX = boundsF.Left; // Convenient variables, used for left and right closedSideX = boundsF.Right; float equalsOffset = 1.5f * penWidth; topTip = middle - equalsOffset; bottomTip = middle + equalsOffset; g.DrawLine(pen, openSideX, topTip, closedSideX, topTip); g.DrawLine(pen, openSideX, bottomTip, closedSideX, bottomTip); if (slashEquality) { // Clip tighter so that the top and bottom of the lines // are clipped horizontally and don't touch the edge lines. g.ResetClip(); boundsF.Inflate(0f, -penWidth * 1.25f); g.SetClip(boundsF); g.DrawLine(pen, openSideX + penWidth, boundsF.Bottom, closedSideX - penWidth, boundsF.Top); } } g.ResetClip(); // Restore the pen color if (updateColor) { pen.Color = startColor; } } }
/// <summary> /// Copy of <see cref="TextField.DoPaint"/> modified to support the /// <see cref="IDynamicColorGeometryHost"/> on the parent shape. /// </summary> public override void DoPaint(DiagramPaintEventArgs e, ShapeElement parentShape) { DiagramClientView clientView = e.View; if (!HasPendingEdit(parentShape, clientView)) { if (GetVisible(parentShape)) { string text = GetDisplayText(parentShape); StyleSet styleSet = parentShape.StyleSet; Graphics g = e.Graphics; RectangleF clip = g.ClipBounds; clip.Inflate(InflateFocus, InflateFocus); clip.Height -= InflateFocus; g.SetClip(clip); RectangleD shapeBounds = GetBounds(parentShape); RectangleF shapeRect = RectangleD.ToRectangleF(shapeBounds); Matrix startTransform = null; if (!DefaultIsHorizontal) { PointF point = PointD.ToPointF(shapeBounds.Center); startTransform = g.Transform; Matrix verticalTransform = g.Transform; verticalTransform.RotateAt(-90f, point); verticalTransform.Translate(0f, (-point.X / 2f) - shapeRect.X); g.Transform = verticalTransform; } if (parentShape.ClipWhenDrawingFields) { RectangleD parentBounds = parentShape.BoundingBox; shapeRect.Intersect(new RectangleF(0f, 0f, (float)parentBounds.Width, (float)parentBounds.Height)); } if (FillBackground) { Color startColor = Color.White; Brush brush = GetBackgroundBrush(clientView, parentShape, ref startColor); g.FillRectangle(brush, shapeRect); SolidBrush solidBrush = brush as SolidBrush; if (solidBrush != null) { solidBrush.Color = startColor; } } if (DrawBorder) { Color oldColor = Color.White; Pen pen = GetPen(clientView, parentShape, ref oldColor); GeometryUtility.SafeDrawRectangle(g, pen, shapeRect.X, shapeRect.Y, shapeRect.Width, shapeRect.Height); pen.Color = oldColor; } if (text.Length > 0x0) { using (Font font = GetFont(parentShape)) { // Note that this ignores the base GetTextBrush, which is trivial // and has no overrides. Note that we follow the convention used with // the base and do not update luminosity on the text. StyleSetResourceId textBrushId = GetTextBrushId(clientView, parentShape); Brush textBrush = styleSet.GetBrush(textBrushId); Color restoreTextColor = Color.Empty; IDynamicColorGeometryHost dynamicColors = parentShape as IDynamicColorGeometryHost; if (dynamicColors != null) { restoreTextColor = dynamicColors.UpdateDynamicColor(textBrushId, textBrush); } g.DrawString(text, font, textBrush, shapeRect, GetStringFormat(parentShape)); SolidBrush solidTextBrush; if (!restoreTextColor.IsEmpty && null != (solidTextBrush = textBrush as SolidBrush)) { solidTextBrush.Color = restoreTextColor; } } } if (HasFocusedAppearance(parentShape, clientView)) { // Note that the base makes a copy of shapeRect and // assymetrically modifies the focus rectangle. I don't // think this adds anything and gives focus floating shapes a // focus rectangle that arbitrarily overlaps nearby shapes. //RectangleF focusRect = shapeRect; //focusRect.Inflate(0f, InflateFocus); //focusRect.Height -= InflateFocus; //GeometryUtility.SafeDrawRectangle(g, styleSet.GetPen(DiagramPens.FocusIndicatorBackground), focusRect.X, focusRect.Y, focusRect.Width, focusRect.Height); //GeometryUtility.SafeDrawRectangle(g, styleSet.GetPen(DiagramPens.FocusIndicator), focusRect.X, focusRect.Y, focusRect.Width, focusRect.Height); // UNDONE: The bottom line is drawing clipped. The original code has the same problem // with both the top and bottom lines. This appears to be an issue with the Center // alignment on the default focus indicator pens. shapeRect.Inflate(0f, TextFocusTopPadding); shapeRect.Height -= TextFocusTopPadding - TextFocusBottomPadding; GeometryUtility.SafeDrawRectangle(g, styleSet.GetPen(DiagramPens.FocusIndicatorBackground), shapeRect.X, shapeRect.Y, shapeRect.Width, shapeRect.Height); GeometryUtility.SafeDrawRectangle(g, styleSet.GetPen(DiagramPens.FocusIndicator), shapeRect.X, shapeRect.Y, shapeRect.Width, shapeRect.Height); } if (startTransform != null) { g.Transform = startTransform; } } } }