DrawColorCategoryResults
        (
            DrawingObjects oDrawingObjects,
            ICollection <String> oCategoryNames,
            GetShapeAndColorForCategory oShapeAndColorGetter,
            Rectangle oColumnRectangle,
            ref Int32 iTop
        )
        {
            Debug.Assert(oDrawingObjects != null);
            Debug.Assert(oCategoryNames != null);
            AssertValid();

            Graphics oGraphics = oDrawingObjects.Graphics;

            iTop += oDrawingObjects.GetFontHeightMultiple(0.2F);

            // The categories are drawn from left to right.  Each category is drawn
            // as a shape followed by the category name.

            // Calculate the width of one category column.

            Single fShapeWidth     = CategoryShapeFactor * oDrawingObjects.FontHeight;
            Single fShapeHalfWidth = fShapeWidth / 2F;

            Single fColumnWidth = (Single)Math.Ceiling(fShapeWidth +
                                                       (MaximumCategoryNameLength * oDrawingObjects.FontHeight));

            // How many columns will fit?  There must be at least one, even if
            // there isn't enough room for one column.

            Debug.Assert(fColumnWidth > 0);

            Int32 iColumns = Math.Max(1,
                                      (Int32)(oColumnRectangle.Width / fColumnWidth));

            fColumnWidth = (Single)oColumnRectangle.Width / (Single)iColumns;

            Int32  iCategories = oCategoryNames.Count;
            Int32  iColumn     = 0;
            Single fLeft       = oColumnRectangle.Left;

            Pen oPen = new Pen(Color.Black, 1.0F);

            oPen.Alignment = PenAlignment.Inset;

            SolidBrush oBrush = new SolidBrush(Color.Black);

            SmoothingMode eOldSmoothingMode = oGraphics.SmoothingMode;

            oGraphics.SmoothingMode = SmoothingMode.HighQuality;
            Int32 i = 0;

            foreach (String sCategoryName in oCategoryNames)
            {
                // Get the shape and color for this category.

                VertexShape eVertexShape;
                Color       oVertexColor;

                oShapeAndColorGetter(i, out eVertexShape, out oVertexColor);

                DrawVertexCategoryShape(oDrawingObjects, eVertexShape, oPen,
                                        oBrush, oVertexColor,
                                        fLeft + fShapeHalfWidth + 2,
                                        iTop + fShapeHalfWidth + 1,
                                        fShapeHalfWidth);

                // Don't let the category name spill over into the next column.

                Single fTopOffset = fShapeWidth * 0.15F;

                Rectangle oNameRectangle = Rectangle.FromLTRB(
                    (Int32)(fLeft + fShapeWidth * 1.4F),
                    (Int32)(iTop + fTopOffset),
                    (Int32)(fLeft + fColumnWidth),
                    (Int32)(iTop + oDrawingObjects.FontHeight + fTopOffset)
                    );

                oGraphics.DrawString(sCategoryName, oDrawingObjects.Font,
                                     SystemBrushes.WindowText, oNameRectangle,
                                     oDrawingObjects.TrimmingStringFormat);

                if (iCategories > MaximumCategoriesToDraw &&
                    i == MaximumCategoriesToDraw - 1)
                {
                    oGraphics.DrawString(
                        "There are additional categories that are not shown here.",
                        oDrawingObjects.Font, SystemBrushes.WindowText,
                        oColumnRectangle.Left,
                        iTop + 1.5F * oDrawingObjects.FontHeight);

                    iTop += oDrawingObjects.GetFontHeightMultiple(3F);
                    break;
                }

                oGraphics.DrawLine(SystemPens.ControlLight,
                                   oNameRectangle.Right - 1,
                                   iTop,
                                   oNameRectangle.Right - 1,
                                   iTop + oDrawingObjects.GetFontHeightMultiple(1.4F)
                                   );

                iColumn++;
                fLeft += fColumnWidth;
                Boolean bIncrementTop = false;

                if (iColumn == iColumns)
                {
                    iColumn       = 0;
                    fLeft         = oColumnRectangle.Left;
                    bIncrementTop = true;
                }
                else if (i == iCategories - 1)
                {
                    bIncrementTop = true;
                }

                if (bIncrementTop)
                {
                    iTop += oDrawingObjects.GetFontHeightMultiple(1.4F);

                    // Draw a line separating these results from the next.

                    DrawHorizontalSeparator(oDrawingObjects, oColumnRectangle,
                                            ref iTop);

                    iTop += oDrawingObjects.GetFontHeightMultiple(0.2F);
                }

                i++;
            }

            oPen.Dispose();
            oBrush.Dispose();
            oGraphics.SmoothingMode = eOldSmoothingMode;
        }
    DrawColorCategoryResults
    (
        DrawingObjects oDrawingObjects,
        ICollection<String> oCategoryNames,
        GetShapeAndColorForCategory oShapeAndColorGetter,
        Rectangle oColumnRectangle,
        ref Int32 iTop
    )
    {
        Debug.Assert(oDrawingObjects != null);
        Debug.Assert(oCategoryNames != null);
        AssertValid();

        Graphics oGraphics = oDrawingObjects.Graphics;
        iTop += oDrawingObjects.GetFontHeightMultiple(0.2F);

        // The categories are drawn from left to right.  Each category is drawn
        // as a shape followed by the category name.

        // Calculate the width of one category column.

        Single fShapeWidth = CategoryShapeFactor * oDrawingObjects.FontHeight;
        Single fShapeHalfWidth = fShapeWidth / 2F;

        Single fColumnWidth = (Single)Math.Ceiling( fShapeWidth +
            (MaximumCategoryNameLength * oDrawingObjects.FontHeight) );

        // How many columns will fit?  There must be at least one, even if
        // there isn't enough room for one column.

        Debug.Assert(fColumnWidth > 0);

        Int32 iColumns = Math.Max( 1,
            (Int32)(oColumnRectangle.Width / fColumnWidth) );

        fColumnWidth = (Single)oColumnRectangle.Width / (Single)iColumns;

        Int32 iCategories = oCategoryNames.Count;
        Int32 iColumn = 0;
        Single fLeft = oColumnRectangle.Left;

        Pen oPen = new Pen(Color.Black, 1.0F);
        oPen.Alignment = PenAlignment.Inset;

        SolidBrush oBrush = new SolidBrush(Color.Black);

        SmoothingMode eOldSmoothingMode = oGraphics.SmoothingMode;
        oGraphics.SmoothingMode = SmoothingMode.HighQuality;
        Int32 i = 0;

        foreach (String sCategoryName in oCategoryNames)
        {
            // Get the shape and color for this category.

            VertexShape eVertexShape;
            Color oVertexColor;

            oShapeAndColorGetter(i, out eVertexShape, out oVertexColor);

            DrawVertexCategoryShape(oDrawingObjects, eVertexShape, oPen,
                oBrush, oVertexColor,
                fLeft + fShapeHalfWidth + 2,
                iTop + fShapeHalfWidth + 1,
                fShapeHalfWidth);

            // Don't let the category name spill over into the next column.

            Single fTopOffset = fShapeWidth * 0.15F;

            Rectangle oNameRectangle = Rectangle.FromLTRB(
                (Int32)(fLeft + fShapeWidth * 1.4F),
                (Int32)(iTop + fTopOffset),
                (Int32)(fLeft + fColumnWidth),
                (Int32)(iTop + oDrawingObjects.FontHeight + fTopOffset)
                );

            oGraphics.DrawString(sCategoryName, oDrawingObjects.Font,
                SystemBrushes.WindowText, oNameRectangle,
                oDrawingObjects.TrimmingStringFormat);

            if (iCategories > MaximumCategoriesToDraw &&
                i == MaximumCategoriesToDraw - 1)
            {
                oGraphics.DrawString(
                    "There are additional categories that are not shown here.",
                    oDrawingObjects.Font, SystemBrushes.WindowText,
                    oColumnRectangle.Left,
                    iTop + 1.5F * oDrawingObjects.FontHeight);

                iTop += oDrawingObjects.GetFontHeightMultiple(3F);
                break;
            }

            oGraphics.DrawLine( SystemPens.ControlLight,
                oNameRectangle.Right - 1,
                iTop,
                oNameRectangle.Right - 1,
                iTop + oDrawingObjects.GetFontHeightMultiple(1.4F)
                );

            iColumn++;
            fLeft += fColumnWidth;
            Boolean bIncrementTop = false;

            if (iColumn == iColumns)
            {
                iColumn = 0;
                fLeft = oColumnRectangle.Left;
                bIncrementTop = true;
            }
            else if (i == iCategories - 1)
            {
                bIncrementTop = true;
            }

            if (bIncrementTop)
            {
                iTop += oDrawingObjects.GetFontHeightMultiple(1.4F);

                // Draw a line separating these results from the next.

                DrawHorizontalSeparator(oDrawingObjects, oColumnRectangle,
                    ref iTop);

                iTop += oDrawingObjects.GetFontHeightMultiple(0.2F);
            }

            i++;
        }

        oPen.Dispose();
        oBrush.Dispose();
        oGraphics.SmoothingMode = eOldSmoothingMode;
    }