Esempio n. 1
0
        /*
         * This routine is used to invert the hole points, specifically the 'Y' points.
         * The html canvas has 0,0 at the upper left and 'Y' goes down. For the holegroup canvas
         * we want a 'Y' that goes up, because that's how the holes are overlaid and appear in
         * three dimensions, and how we think of them intuitively. To manage this we'll simply flip the
         * Y points for the duration of the time that they are being edited and reflip them when its time to save
         */
        public void InvertHolePoints()
        {
            for (int i = 0; i < HoleGroupList.Count; i++)
            {
                HoleGroup hg = HoleGroupList.GetFrom(i);

                for (int j = 0; j < hg.HoleList.Length; j++)
                {
                    /*
                     * For all hole types the offset Y is inverted
                     */
                    LayoutHole oHole = hg.HoleList[j];
                    oHole.OffsetY = -oHole.OffsetY;

                    /*
                     * For polygon hole types the individual Y's are inverted
                     */
                    if (oHole.HoleType == "poly")
                    {
                        BoundaryPolygon oPolygon = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex);
                        for (int k = 0; k < oPolygon.PointList.Length; k++)
                        {
                            Point3D p = oPolygon.PointList[k];
                            p.Y = -p.Y;
                        }
                    }
                }
            }
        }
        //----------------------------------------------------------------------------
        private bool TrySelectEllipse(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY)
        {
            PointF MoveHandle   = new PointF(0, 0);
            PointF ResizeHandle = new PointF(0, 0);

            BoundaryEllipse oEllipse = BoundaryEllipseList.GetFrom(oHole.HoleTypeIndex);

            // The move handle  is the center
            MoveHandle = this.W2S(oHole.OffsetX, oHole.OffsetY);
            if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, MoveHandle))
            {
                CurrentlySelectedHole       = oHole;
                MostRecentlySelectedHole    = oHole;
                CurrentlySelectedHandleType = eHandleType.MoveHandle;
                return(true);
            }

            // The resize handle is the lower right corner
            ResizeHandle = this.W2S(oHole.OffsetX + oEllipse.Width / 2, oHole.OffsetY + oEllipse.Height / 2);
            if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, ResizeHandle))
            {
                CurrentlySelectedHole       = oHole;
                MostRecentlySelectedHole    = oHole;
                CurrentlySelectedHandleType = eHandleType.ResizeHandle;
                return(true);
            }

            return(false);
        }
Esempio n. 3
0
        //----------------------------------------------------------------------------
        private bool TrySelectRectangle(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY)
        {
            PointF MoveHandle   = new PointF(0, 0);
            PointF ResizeHandle = new PointF(0, 0);

            BoundaryRectangle oRect = BoundaryRectangleList.GetFrom(oHole.HoleTypeIndex);

            // The move handle  is the lower left
            MoveHandle = this.W2S(oHole.OffsetX, oHole.OffsetY);
            if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, MoveHandle))
            {
                CurrentlySelectedHole       = oHole;
                MostRecentlySelectedHole    = oHole;
                CurrentlySelectedHandleType = eHandleType.MoveHandle;
                return(true);
            }

            // The resize handle is the lower right corner
            // the position of the handle is based on the zoom

            float HandleOffsetX = oRect.Width / this.CurrentZoom;
            float HandleOffsetY = oRect.Height / this.CurrentZoom;

            ResizeHandle = new PointF(MoveHandle.X + HandleOffsetX, MoveHandle.Y + HandleOffsetY);

            if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, ResizeHandle))
            {
                CurrentlySelectedHole       = oHole;
                MostRecentlySelectedHole    = oHole;
                CurrentlySelectedHandleType = eHandleType.ResizeHandle;
                return(true);
            }

            return(false);
        }
        //------------------------------------------------------
        private void DrawShapes_Polygon(LayoutHole oHole, bool IsCurrentHole)
        {
            BoundaryPolygon bp = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex);

            PointF ScreenOffset = this.W2S(oHole.OffsetX, oHole.OffsetY);

            for (int i = 0; i < bp.PointList.Length; i++)
            {
                int FromIndex = i;
                int ToIndex   = i + 1;
                if (ToIndex == bp.PointList.Length)
                {
                    ToIndex = 0;                                 // Wrap at end
                }
                Point3D FromPoint = bp.PointList[FromIndex];

                float fdx = FromPoint.X / CurrentZoom;
                float fdy = FromPoint.Y / CurrentZoom;

                Point3D ToPoint = bp.PointList[ToIndex];

                float tdx = ToPoint.X / CurrentZoom;
                float tdy = ToPoint.Y / CurrentZoom;

                PointF ScreenFrom = new PointF(ScreenOffset.X + fdx, ScreenOffset.Y + fdy);
                PointF ScreenTo   = new PointF(ScreenOffset.X + tdx, ScreenOffset.Y + tdy);

                // Draw handles
                string color = "rgba(255,0,0,.5)";
                if (IsCurrentHole && i == MostRecentlySelectedPolygonVertexIndex)
                {
                    color = "#0000FF";
                }
                this.DrawCircle(color, 10, ScreenFrom.X, ScreenFrom.Y);

                PointF oCenter = EdgeCenter(ScreenFrom, ScreenTo);
                // Draw the handle for the edge
                color = "rgba(0,255,0,.5)";
                if (IsCurrentHole && i == MostRecentlySelectedPolygonEdgeIndex)
                {
                    color = "#0000FF";
                }
                this.DrawRectangle(color, 10, 10, oCenter.X, oCenter.Y);

                // Draw Line
                this.DrawLine(ShapeStrokeColor, (float)0.5, ScreenFrom, ScreenTo);

                // Draw the move handle
                PointF oMove = PolygonCenter(bp);
                float  mdx   = oMove.X / CurrentZoom;
                float  mdy   = oMove.Y / CurrentZoom;

                oMove = new PointF(ScreenOffset.X + mdx, ScreenOffset.Y + mdy);
                color = IsCurrentHole ? "#0000FF" : "rgba(255,0,0,.5)";

                // Draw the move handle
                this.DrawCircle(color, 10, oMove.X, oMove.Y);
            }
        }
        public void AddHoleToHoleGroup(HoleGroup hg, LayoutHole oNewHole)
        {
#if DOTNET
            List <LayoutHole> tmp = new List <LayoutHole>(hg.HoleList);
            tmp.Add(oNewHole);
            hg.HoleList = tmp.ToArray();
#else
            hg.HoleList.push(oNewHole);
#endif
        }
Esempio n. 6
0
        // Add a polygon. This is managed with a simplelayout object
        public void AddPolygon(int ScreenOffsetX, int ScreenOffsetY, int InitialSides, int Radius)
        {
            if (MostRecentlySelectedHoleGroup == null)
            {
                return;
            }

            BoundaryPolygon oPolygon = new BoundaryPolygon();

            oPolygon.PointList = new Point3D[InitialSides];

            float Angle      = 0;
            float AngleDelta = (float)Math.PI * 2 / InitialSides;

            for (int i = 0; i < InitialSides; i++)
            {
                Point3D p = new Point3D();
#if DOTNET
                float x = (float)Math.Cos(Angle) * Radius;
                float y = (float)Math.Sin(Angle) * Radius;
#else
                float x = (float)Math.cos(Angle) * Radius;
                float y = (float)Math.sin(Angle) * Radius;
#endif
                p.X = x;
                p.Y = y;

                oPolygon.PointList[i] = p;

                Angle += AngleDelta;
            }

            /*
             * Create a hole and boundary polygon object
             */
            PointF     WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY);
            LayoutHole oHole       = new LayoutHole();
            oHole.HoleType      = "poly";
            oHole.HoleTypeIndex = BoundaryPolygonList.Count;
            oHole.OffsetX       = WorldOffset.X;
            oHole.OffsetY       = WorldOffset.Y;

            AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole);

            CurrentlySelectedHole    = oHole;
            MostRecentlySelectedHole = oHole;

            BoundaryPolygonList.Add(oPolygon);

            // trigger redraw

            DrawShapes();
        }
Esempio n. 7
0
        public void LoadFromJSON(
            HoleGroup[] HoleGroupArray,
            BoundaryRectangle[] RectangleArray,
            BoundaryEllipse[] EllipseArray,
            BoundaryPolygon[] PolygonArray)
        {
            HoleGroupList = new List <HoleGroup>();
            for (int i = 0; i < HoleGroupArray.Length; i++)
            {
                HoleGroup hg = new HoleGroup();

                hg.HoleGroupID = HoleGroupArray[i].HoleGroupID;

                /*
                 * When the objects get here in JS the holelist is no longer a list type, its an array type because
                 * of serialization.
                 */
                int len = GetHoleListLength(HoleGroupArray[i].HoleList);
                for (int j = 0; j < len; j++)
                {
                    LayoutHole oHoleToAdd = HoleGroupArray[i].HoleList[j];

                    AddHoleToHoleGroup(hg, oHoleToAdd);
                }

                HoleGroupList.Add(hg);
            }

            BoundaryRectangleList = new List <BoundaryRectangle>();
            for (int i = 0; i < RectangleArray.Length; i++)
            {
                BoundaryRectangleList.Add(RectangleArray[i]);
            }

            BoundaryEllipseList = new List <BoundaryEllipse>();
            for (int i = 0; i < EllipseArray.Length; i++)
            {
                BoundaryEllipseList.Add(EllipseArray[i]);
            }

            BoundaryPolygonList = new List <BoundaryPolygon>();
            for (int i = 0; i < PolygonArray.Length; i++)
            {
                BoundaryPolygonList.Add(PolygonArray[i]);
            }

            /*
             * Now flip all of the Y points so that positive Y values go 'up'
             */
            InvertHolePoints();
        }
        public void DuplicateCurrentHole()
        {
            if (MostRecentlySelectedHole == null)
            {
                return;
            }

            LayoutHole oHole = LayoutHole.CopyFrom(MostRecentlySelectedHole);

            // Add at an offset so it will be easy to see
            oHole.OffsetX += 10;
            oHole.OffsetY += 10;

            // Create a new version of the instance of the hole

            int ndx = MostRecentlySelectedHole.HoleTypeIndex;

            switch (MostRecentlySelectedHole.HoleType)
            {
            case "ell":
                oHole.HoleTypeIndex = BoundaryEllipseList.Count;
                BoundaryEllipse e = BoundaryEllipseList.GetFrom(ndx);
                BoundaryEllipseList.Add(BoundaryEllipse.CopyFrom(e));
                break;

            case "rect":
                oHole.HoleTypeIndex = BoundaryRectangleList.Count;
                BoundaryRectangle r = BoundaryRectangleList.GetFrom(ndx);
                BoundaryRectangleList.Add(BoundaryRectangle.CopyFrom(r));
                break;

            case "poly":
                oHole.HoleTypeIndex = BoundaryPolygonList.Count;
                BoundaryPolygon p = BoundaryPolygonList.GetFrom(ndx);
                BoundaryPolygonList.Add(BoundaryPolygon.CopyFrom(p));
                break;
            }

            // Add the new hole to the hole group
            AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole);

            // trigger a repaint
            DrawShapes();
        }
Esempio n. 9
0
        public void AddEllipse(int ScreenOffsetX, int ScreenOffsetY, int Width, int Height)
        {
            if (MostRecentlySelectedHoleGroup == null)
            {
                return;
            }

            PointF WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY);

            LayoutHole oHole = new LayoutHole();

            oHole.HoleType = "ell";
            oHole.OffsetX  = WorldOffset.X;
            oHole.OffsetY  = WorldOffset.Y;

            /*
             * Save this as the current and most recently selected
             * The most recently selected is used for commands after the mouse is up
             */
            CurrentlySelectedHole    = oHole;
            MostRecentlySelectedHole = oHole;

            /*
             * The index is the at the end of the current list. This means we will have to manage the index values
             * when they are deleted
             */
            oHole.HoleTypeIndex = BoundaryEllipseList.Count;
            AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole);

            /*
             * Now create and add the ellipse
             */
            BoundaryEllipse ell = new BoundaryEllipse();

            ell.Width  = Width;
            ell.Height = Height;

            BoundaryEllipseList.Add(ell);

            // trigger redraw

            DrawShapes();
        }
Esempio n. 10
0
        public void AddRectangle(int ScreenOffsetX, int ScreenOffsetY, int Width, int Height)
        {
            if (MostRecentlySelectedHoleGroup == null)
            {
                return;
            }

            PointF WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY);

            LayoutHole oHole = new LayoutHole();

            oHole.HoleType = "rect";
            oHole.OffsetX  = WorldOffset.X;
            oHole.OffsetY  = WorldOffset.Y;

            /*
             * Save this as the current and most recently selected
             */
            CurrentlySelectedHole    = oHole;
            MostRecentlySelectedHole = oHole;

            /*
             * The index is the at the end of the current list. This means we will have to manage the index values
             * when they are deleted
             */
            oHole.HoleTypeIndex = BoundaryRectangleList.Count;

            AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole);

            /*
             * Now create and add the rectangle
             */
            BoundaryRectangle rect = new BoundaryRectangle();

            rect.Width  = Width;
            rect.Height = Height;

            BoundaryRectangleList.Add(rect);

            // trigger draw shapes
            DrawShapes();
        }
        //-------------------------------------------------------
        private void DrawShapes_Ellipse(LayoutHole oHole, bool IsCurrentHole)
        {
            BoundaryEllipse oEllipse = BoundaryEllipseList.GetFrom(oHole.HoleTypeIndex);

            PointF Screen = this.W2S(oHole.OffsetX, oHole.OffsetY);

            float SWidth  = oEllipse.Width / CurrentZoom;
            float SHeight = oEllipse.Height / CurrentZoom;

            string color = IsCurrentHole ? "#0000FF" : "rgba(255,0,0,.5)";

            // Draw the move handle
            this.DrawCircle(color, 10, Screen.X, Screen.Y);

            // draw the actual ellipse
            this.DrawEllipse(ShapeStrokeColor, SWidth, SHeight, Screen.X, Screen.Y);

            // draw the resize handle
            this.DrawRectangle("rgba(0,255,0,.5)", 10, 10, Screen.X + SWidth / 2, Screen.Y + SHeight / 2);
        }
Esempio n. 12
0
        /// <summary>
        /// Find the edge that's closest to the mouse X,Y
        /// </summary>
        /// <param name="ScreenMouseX"></param>
        /// <param name="ScreenMouseY"></param>
        /// <returns></returns>
        ///
        public bool TryHoleSelect(int ScreenMouseX, int ScreenMouseY)
        {
            if (MostRecentlySelectedHoleGroup == null)
            {
                return(false);
            }

            for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++)
            {
                LayoutHole oHole        = MostRecentlySelectedHoleGroup.HoleList[i];
                PointF     MoveHandle   = new PointF(0, 0);
                PointF     ResizeHandle = new PointF(0, 0);

                switch (oHole.HoleType)
                {
                case "rect":
                    if (TrySelectRectangle(oHole, ScreenMouseX, ScreenMouseY))
                    {
                        return(true);
                    }
                    break;

                case "poly":
                    if (TrySelectPolygon(oHole, ScreenMouseX, ScreenMouseY))
                    {
                        return(true);
                    }
                    break;

                case "ell":
                    if (TrySelectEllipse(oHole, ScreenMouseX, ScreenMouseY))
                    {
                        return(true);
                    }
                    break;
                }
            }

            return(false);
        }
        //-------------------------------------------------------
        private void DrawShapes_Rectangle(LayoutHole oHole, bool IsCurrentHole)
        {
            BoundaryRectangle oRect = BoundaryRectangleList.GetFrom(oHole.HoleTypeIndex);

            PointF Screen = this.W2S(oHole.OffsetX, oHole.OffsetY);

            string color = IsCurrentHole ? "#0000FF" : "#ff0000";

            // Draw the move handle
            this.DrawCircle(color, HandleSize, Screen.X, Screen.Y);

            // Adjust the width and height for zoom
            float SWidth  = oRect.Width / CurrentZoom;
            float SHeight = oRect.Height / CurrentZoom;

            // Draw the rectangle as a set of lines so we can control how its positioned. The offset is the lower left
            color = ShapeStrokeColor;

            // The offset is to the lower left
            PointF LowerLeft = Screen;

            PointF LowerRight = new PointF(LowerLeft.X + SWidth, LowerLeft.Y);

            this.DrawLine(color, 1, LowerLeft, LowerRight);

            PointF UpperRight = new PointF(LowerLeft.X + SWidth, LowerLeft.Y + SHeight);

            this.DrawLine(color, 1, LowerRight, UpperRight);

            PointF UpperLeft = new PointF(LowerLeft.X, LowerLeft.Y + SHeight);

            this.DrawLine(color, 1, UpperRight, UpperLeft);

            // Last line
            this.DrawLine(color, 1, UpperLeft, LowerLeft);

            // draw the resize handle
            this.DrawRectangle("#00FF00", HandleSize, HandleSize, Screen.X + SWidth, Screen.Y + SHeight - HandleSize);
        }
Esempio n. 14
0
        public void DeleteCurrentHole()
        {
            if (MostRecentlySelectedHole == null)
            {
                return;
            }

            int IndexToDelete = -1;

            switch (MostRecentlySelectedHole.HoleType)
            {
            case "ell":
                // Delete this index
                // Find all references to hole values greater than this one and reduce them by one so the indices are correct
                IndexToDelete = -1;

                for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++)
                {
                    LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i];

                    if (MostRecentlySelectedHole == oHole)
                    {
                        IndexToDelete = i;
                    }

                    if (oHole.HoleType == "ell" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex)
                    {
                        oHole.HoleTypeIndex--;
                    }
                }

                // Delete this hole
                RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete);

                // Delete this shape
                BoundaryEllipseList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex);
                break;

            case "rect":
                // Delete this index
                // Find all references to hole values greater than this one and reduce them by one so the indices are correct
                IndexToDelete = -1;
                for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++)
                {
                    LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i];

                    if (MostRecentlySelectedHole == oHole)
                    {
                        IndexToDelete = i;
                    }

                    if (oHole.HoleType == "rect" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex)
                    {
                        oHole.HoleTypeIndex--;
                    }
                }

                // Delete this hole
                RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete);

                // Delete this shape
                BoundaryRectangleList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex);
                break;

            case "poly":

                // Find all references to hole values greater than this one and reduce them by one so the indices are correct
                IndexToDelete = -1;

                for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++)
                {
                    LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i];

                    if (MostRecentlySelectedHole == oHole)
                    {
                        IndexToDelete = i;
                    }

                    if (oHole.HoleType == "poly" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex)
                    {
                        oHole.HoleTypeIndex--;
                    }
                }

                // Delete this hole
                RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete);

                // Delete this shape
                BoundaryPolygonList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex);
                break;
            }

            // trigger a repaint
            DrawShapes();
        }
Esempio n. 15
0
        //--------------------------------------------------------------------------

        /*
         * A Polygon can be selected in any of these ways:
         * 1. A vertex can be selected, which makes it the active vertex
         * 2. An edge can be selected, which makes it the active edge
         * 3. The move handle can be selected. The move handle is generated as the average of the points of the polygon
         */
        private bool TrySelectPolygon(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY)
        {
            PointF MoveHandle = new PointF(0, 0);
            float  dx;
            float  dy;


            BoundaryPolygon oPolygon = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex);

            PointF ScreenOffset = this.W2S(oHole.OffsetX, oHole.OffsetY);

            /*
             * See if this is one of the vertices
             */
            for (int i = 0; i < oPolygon.PointList.Length; i++)
            {
                Point3D p = oPolygon.PointList[i];
                dx = p.X / CurrentZoom;
                dy = p.Y / CurrentZoom;

                PointF Target = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy);

                if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, Target))
                {
                    CurrentlySelectedHole = oHole;
                    // Most recently selected is used for commands that happen after the mouse is up
                    MostRecentlySelectedHole    = oHole;
                    CurrentlySelectedHandleType = eHandleType.VertexHandle;

                    CurrentlySelectedPolygonVertexIndex = i;
                    // The most recently used is for commands that happen after the mouse is up
                    MostRecentlySelectedPolygonVertexIndex = i;

                    return(true);
                }
            }

            /*
             * See if this is one of the edges
             */
            for (int i = 0; i < oPolygon.PointList.Length; i++)
            {
                int FromIndex = i;
                int ToIndex   = i + 1;
                if (ToIndex == oPolygon.PointList.Length)
                {
                    ToIndex = 0;
                }

                Point3D FromPoint = oPolygon.PointList[FromIndex];

                dx = FromPoint.X / CurrentZoom;
                dy = FromPoint.Y / CurrentZoom;

                PointF pFrom = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy);

                Point3D ToPoint = oPolygon.PointList[ToIndex];

                dx = ToPoint.X / CurrentZoom;
                dy = ToPoint.Y / CurrentZoom;

                PointF pTo = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy);

                PointF Target = EdgeCenter(pFrom, pTo);

                if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, Target))
                {
                    CurrentlySelectedHole = oHole;
                    // Most recently selected is used for commands that happen after the mouse is up
                    MostRecentlySelectedHole    = oHole;
                    CurrentlySelectedHandleType = eHandleType.EdgeHandle;

                    CurrentlySelectedPolygonEdgeIndex = i;
                    // The most recently used is for commands that happen after the mouse is up
                    MostRecentlySelectedPolygonEdgeIndex = i;

                    return(true);
                }
            }

            /*
             * See if this is the move handle at the center of the polygon
             */
            PointF pCenter = PolygonCenter(oPolygon);

            dx      = pCenter.X / CurrentZoom;
            dy      = pCenter.Y / CurrentZoom;
            pCenter = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy);

            if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, pCenter))
            {
                CurrentlySelectedHole = oHole;
                // Most recently selected is used for commands that happen after the mouse is up
                MostRecentlySelectedHole    = oHole;
                CurrentlySelectedHandleType = eHandleType.MoveHandle;
                return(true);
            }


            return(false);
        }
Esempio n. 16
0
        // ---------------------------------------------------
        public override void DrawShapes()
        {
#if DOTNET
            // The model for .net is to invalidate and let the paint handler draw.
            if (oGraphics == null && DrawPrimitives == null)
            {
                return;
            }
#else
#endif
            bool bIsCurrentHole = false;
            if (SubControl == 0)
            {
                this.Clear("#FFFFFF");

                DrawGrid();

                DrawAxis();
            }

            /*
             * If specified draw in a shaded area that represents the current edge having holes designed for it
             */
            if (ShadeHeight > 0 && ShadeLength > 0)
            {
                PointF LowerLeft  = this.W2S(0, 0);
                PointF LowerRight = this.W2S(ShadeLength, 0);
                PointF UpperRight = this.W2S(ShadeLength, -ShadeHeight);
                PointF UpperLeft  = this.W2S(0, -ShadeHeight);

                this.DrawLine("rgba(100,100,150,.7", 1, LowerLeft, LowerRight);
                this.DrawLine("rgba(100,100,150,.7", 1, LowerRight, UpperRight);
                this.DrawLine("rgba(100,100,150,.7", 1, UpperRight, UpperLeft);
                this.DrawLine("rgba(100,100,150,.7", 1, UpperLeft, LowerLeft);
            }

            if (this.MostRecentlySelectedHoleGroup == null)
            {
                return;
            }

#if DOTNET
            int len = MostRecentlySelectedHoleGroup.HoleList.Length;
#else
            int len = MostRecentlySelectedHoleGroup.HoleList.length;
#endif

            for (int i = 0; i < len; i++)
            {
                LayoutHole oHole  = MostRecentlySelectedHoleGroup.HoleList[i];
                PointF     Screen = this.W2S(oHole.OffsetX, oHole.OffsetY);

                bIsCurrentHole = oHole == MostRecentlySelectedHole;

                switch (oHole.HoleType)
                {
                case "rect":

                    DrawShapes_Rectangle(oHole, bIsCurrentHole);
                    break;

                case "poly":

                    DrawShapes_Polygon(oHole, bIsCurrentHole);
                    break;

                case "ell":

                    DrawShapes_Ellipse(oHole, bIsCurrentHole);
                    break;
                }
            }
        }