/// <summary>
        /// DeleteRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.ExclusiveOrConstraintCoupler), FireTime=TopLevelCommit, Priority=DiagramFixupConstants.AddShapeRulePriority;
        /// Split a single shape into two shapes when a exclusion constraint
        /// is decoupled from a mandatory constraint
        /// </summary>
        private static void ExclusiveOrCouplerDeletedRule(ElementDeletedEventArgs e)
        {
            ExclusiveOrConstraintCoupler link      = e.ModelElement as ExclusiveOrConstraintCoupler;
            MandatoryConstraint          mandatory = link.MandatoryConstraint;
            ExclusionConstraint          exclusion = link.ExclusionConstraint;

            if (!mandatory.IsDeleted && !exclusion.IsDeleted)
            {
                LinkedElementCollection <PresentationElement> pels = PresentationViewsSubject.GetPresentation(mandatory);
                int pelCount = pels.Count;
                for (int i = 0; i < pelCount; ++i)
                {
                    ExternalConstraintShape shape = pels[i] as ExternalConstraintShape;
                    if (shape != null)
                    {
                        ORMDiagram diagram = (ORMDiagram)shape.Diagram;
                        RectangleD bounds  = shape.AbsoluteBounds;
                        double     width   = bounds.Width;
                        bounds.Offset(-width / 2, 0);
                        bounds = diagram.BoundsRules.GetCompliantBounds(shape, bounds);
                        shape.AbsoluteBounds = bounds;
                        bounds.Offset(width, 0);
                        diagram.PlaceORMElementOnDiagram(null, exclusion, bounds.Location, ORMPlacementOption.None, null, null);
                    }
                }
            }
        }
        /// <summary>
        /// AddRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.ExclusiveOrConstraintCoupler), FireTime=TopLevelCommit, Priority=DiagramFixupConstants.AddShapeRulePriority;
        /// Remove shapes associated with the exclusion constraint
        /// when exclusion and mandatory constraints are coupled.
        /// </summary>
        private static void ExclusiveOrCouplerAddedRule(ElementAddedEventArgs e)
        {
            ExclusiveOrConstraintCoupler link                  = e.ModelElement as ExclusiveOrConstraintCoupler;
            MandatoryConstraint          mandatory             = link.MandatoryConstraint;
            ExclusionConstraint          exclusion             = link.ExclusionConstraint;
            LinkedElementCollection <PresentationElement> pels = PresentationViewsSubject.GetPresentation(exclusion);

            for (int i = pels.Count - 1; i >= 0; --i)
            {
                ExternalConstraintShape shape = pels[i] as ExternalConstraintShape;
                if (shape != null)
                {
                    shape.Delete();
                }
            }
            InvalidateAssociatedDisplay(mandatory);
        }
        /// <summary>
        /// Overrideable shape painting for use after the paint helper is initialized
        /// </summary>
        /// <param name="e">The event arguments</param>
        /// <param name="helper">The initialized pain helper.</param>
        protected virtual void OnPaintShape(DiagramPaintEventArgs e, ref PaintHelper helper)
        {
            IConstraint  constraint = AssociatedConstraint;
            RectangleD   bounds     = AbsoluteBounds;
            RectangleF   boundsF    = RectangleD.ToRectangleF(bounds);
            Graphics     g          = e.Graphics;
            const double cos45      = 0.70710678118654752440084436210485;

            Pen   pen          = helper.Pen;
            Brush brush        = helper.Brush;
            bool  noDeonticDot = false;

            switch (constraint.ConstraintType)
            {
                #region Frequency
            case ConstraintType.Frequency:
            {
                break;
            }

                #endregion
                #region Ring
            case ConstraintType.Ring:
                // Note: goto default here restores the frowny face. However,
                // with the error feedback, we already have UI indicating there
                // is a problem.
                noDeonticDot = true;
                break;

                #endregion
                #region ValueComparison
            case ConstraintType.ValueComparison:
                noDeonticDot = true;
                break;

                #endregion                 // ValueComparison
                #region Equality
            case ConstraintType.Equality:
            {
                double xOffset = bounds.Width * .3;
                float  xLeft   = (float)(bounds.Left + xOffset);
                float  xRight  = (float)(bounds.Right - xOffset);
                double yCenter = bounds.Top + bounds.Height / 2;
                double yOffset = (double)pen.Width * 1.0;
                float  y       = (float)(yCenter - yOffset);
                g.DrawLine(pen, xLeft, y, xRight, y);
                y = (float)(yCenter + yOffset);
                g.DrawLine(pen, xLeft, y, xRight, y);
                break;
            }

                #endregion
                #region Mandatory
            case ConstraintType.DisjunctiveMandatory:
            {
                // Draw the dot
                RectangleF shrinkBounds = boundsF;
                shrinkBounds.Inflate(-boundsF.Width * .22f, -boundsF.Height * .22f);
                g.FillEllipse(brush, shrinkBounds);
                if (null != ExclusiveOrConstraintCoupler.GetExclusiveOrExclusionConstraint((MandatoryConstraint)constraint))
                {
                    goto case ConstraintType.Exclusion;
                }
                break;
            }

                #endregion
                #region Exclusion
            case ConstraintType.Exclusion:
            {
                // Draw the X
                double offset  = (bounds.Width + pen.Width) * (1 - cos45) / 2;
                float  leftX   = (float)(bounds.Left + offset);
                float  rightX  = (float)(bounds.Right - offset);
                float  topY    = (float)(bounds.Top + offset);
                float  bottomY = (float)(bounds.Bottom - offset);
                g.DrawLine(pen, leftX, topY, rightX, bottomY);
                g.DrawLine(pen, leftX, bottomY, rightX, topY);
                break;
            }

                #endregion
                #region Uniqueness
            case ConstraintType.ExternalUniqueness:
            {
                // Draw a single line for a uniqueness constraint and a double
                // line for preferred uniqueness
                UniquenessConstraint euc = constraint as UniquenessConstraint;
                double widthAdjust       = (double)pen.Width / 2;
                float  xLeft             = (float)(bounds.Left + widthAdjust);
                float  xRight            = (float)(bounds.Right - widthAdjust);
                if (euc.IsPreferred)
                {
                    double yCenter = bounds.Top + bounds.Height / 2;
                    double yOffset = (double)pen.Width * .7;
                    float  y       = (float)(yCenter - yOffset);
                    g.DrawLine(pen, xLeft, y, xRight, y);
                    y = (float)(yCenter + yOffset);
                    g.DrawLine(pen, xLeft, y, xRight, y);
                }
                else
                {
                    float y = (float)(bounds.Top + bounds.Height / 2);
                    g.DrawLine(pen, xLeft, y, xRight, y);
                }
                break;
            }

                #endregion
                #region Subset
            case ConstraintType.Subset:
            {
                RectangleD arcBounds = bounds;
                double     shrinkBy  = -bounds.Height * .35;
                double     yOffset   = pen.Width * .7;
                double     xOffset   = shrinkBy * .35;
                arcBounds.Inflate(shrinkBy, shrinkBy);
                arcBounds.Offset(xOffset, -yOffset);
                g.DrawArc(pen, RectangleD.ToRectangleF(arcBounds), 90, 180);
                float xLeft  = (float)arcBounds.Center.X;
                float xRight = (float)(bounds.Right + shrinkBy - xOffset);
                float y      = (float)arcBounds.Top;
                g.DrawLine(pen, xLeft, y, xRight, y);
                y = (float)arcBounds.Bottom;
                g.DrawLine(pen, xLeft, y, xRight, y);
                y = (float)(arcBounds.Bottom + yOffset + yOffset);
                g.DrawLine(pen, (float)arcBounds.Left, y, xRight, y);
                break;
            }

                #endregion
                #region Fallback (default)
            default:
            {
                // Draws a frowny face
                float  eyeY          = boundsF.Y + (boundsF.Height / 3);
                PointF leftEyeStart  = new PointF(boundsF.X + (boundsF.Width * 0.3f), eyeY);
                PointF leftEyeEnd    = new PointF(boundsF.X + (boundsF.Width * 0.4f), eyeY);
                PointF rightEyeStart = new PointF(boundsF.X + (boundsF.Width * 0.6f), eyeY);
                PointF rightEyeEnd   = new PointF(boundsF.X + (boundsF.Width * 0.7f), eyeY);
                g.DrawLine(pen, leftEyeStart, leftEyeEnd);
                g.DrawLine(pen, rightEyeStart, rightEyeEnd);

                float      mouthLeft      = boundsF.X + (boundsF.Width * 0.25f);
                float      mouthTop       = boundsF.Y + (boundsF.Height * 0.55f);
                RectangleF mouthRectangle = new RectangleF(mouthLeft, mouthTop, boundsF.Width * 0.5f, boundsF.Height * 0.25f);
                g.DrawArc(pen, mouthRectangle, 180, 180);

                break;
            }
                #endregion
            }
            if (!noDeonticDot && constraint.Modality == ConstraintModality.Deontic)
            {
                float startPenWidth = pen.Width;
                pen.Width = startPenWidth * .70f;
                float boxSide = (float)((1 - cos45) * bounds.Width);
                g.FillEllipse(this.StyleSet.GetBrush(DiagramBrushes.DiagramBackground), (float)bounds.Left, (float)bounds.Top, boxSide, boxSide);
                g.DrawArc(pen, (float)bounds.Left, (float)bounds.Top, boxSide, boxSide, 0, 360);
                pen.Width = startPenWidth;
            }
        }