/// <summary>
        /// Raises the PaintBackground event
        /// </summary>
        /// <param name="e">A PaintCellEventArgs that contains the event data</param>
        protected override void OnPaintBackground(PaintCellEventArgs e)
        {
            base.OnPaintBackground(e);

            // don't bother going any further if the Cell is null
            if (e.Cell == null)
            {
                return;
            }

            // get the button state
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);
            PushButtonStates   state        = rendererData.ButtonState;

            // if the cell has focus and is in its normal state,
            // make the button look like a default button
            if (state == PushButtonStates.Normal && e.Focused)
            {
                state = PushButtonStates.Default;
            }

            // if the table is not enabled, make sure the button is disabled
            if (!e.Enabled)
            {
                state = PushButtonStates.Disabled;
            }

            // draw the button
            ThemeManager.DrawButton(e.Graphics, this.CalcButtonBounds(), state);
        }
        /// <summary>
        /// Raises the MouseEnter event
        /// </summary>
        /// <param name="e">A CellMouseEventArgs that contains the event data</param>
        public override void OnMouseEnter(CellMouseEventArgs e)
        {
            base.OnMouseEnter(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            // if the mouse is inside the button, make sure it is "hot"
            if (this.CalcButtonBounds().Contains(e.X, e.Y))
            {
                if (rendererData.ButtonState != PushButtonStates.Hot)
                {
                    rendererData.ButtonState = PushButtonStates.Hot;

                    e.Table.Invalidate(e.CellRect);
                }
            }
            // the mouse isn't inside the button, so it is in its normal state
            else
            {
                if (rendererData.ButtonState != PushButtonStates.Normal)
                {
                    rendererData.ButtonState = PushButtonStates.Normal;

                    e.Table.Invalidate(e.CellRect);
                }
            }
        }
        /// <summary>
        /// Gets the ButtonCellRenderer specific data used by the Renderer from
        /// the specified Cell
        /// </summary>
        /// <param name="cell">The Cell to get the ButtonCellRenderer data for</param>
        /// <returns>The ButtonCellRenderer data for the specified Cell</returns>
        protected ButtonRendererData GetButtonRendererData(Cell cell)
        {
            object rendererData = this.GetRendererData(cell);

            if (rendererData == null || !(rendererData is ButtonRendererData))
            {
                rendererData = new ButtonRendererData();

                this.SetRendererData(cell, rendererData);
            }

            return((ButtonRendererData)rendererData);
        }
        /// <summary>
        /// Raises the MouseLeave event
        /// </summary>
        /// <param name="e">A CellMouseEventArgs that contains the event data</param>
        public override void OnMouseLeave(CellMouseEventArgs e)
        {
            base.OnMouseLeave(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            // make sure the button is in its normal state
            if (rendererData.ButtonState != PushButtonStates.Normal)
            {
                rendererData.ButtonState = PushButtonStates.Normal;

                e.Table.Invalidate(e.CellRect);
            }
        }
        /// <summary>
        /// Raises the KeyDown event
        /// </summary>
        /// <param name="e">A CellKeyEventArgs that contains the event data</param>
        public override void OnKeyDown(CellKeyEventArgs e)
        {
            base.OnKeyDown(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            //
            if (e.KeyData == Keys.Enter || e.KeyData == Keys.Space)
            {
                rendererData.ButtonState = PushButtonStates.Pressed;

                e.Table.Invalidate(e.CellRect);
            }
        }
        /// <summary>
        /// Raises the KeyUp event
        /// </summary>
        /// <param name="e">A CellKeyEventArgs that contains the event data</param>
        public override void OnKeyUp(CellKeyEventArgs e)
        {
            base.OnKeyUp(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            //
            if (e.KeyData == Keys.Enter || e.KeyData == Keys.Space)
            {
                rendererData.ButtonState = PushButtonStates.Normal;

                e.Table.Invalidate(e.CellRect);
                e.Table.OnCellButtonClicked(new CellButtonEventArgs(e.Cell, e.Column, e.Row));
            }
        }
        /// <summary>
        /// Raises the MouseUp event
        /// </summary>
        /// <param name="e">A CellMouseEventArgs that contains the event data</param>
        public override void OnMouseUp(CellMouseEventArgs e)
        {
            base.OnMouseUp(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            // check for the left mouse button
            if (e.Button == MouseButtons.Left)
            {
                Rectangle buttonRect = this.CalcButtonBounds();

                // if the mouse pointer is over the button, make sure
                // the button is "hot"
                if (buttonRect.Contains(e.X, e.Y))
                {
                    rendererData.ButtonState = PushButtonStates.Hot;

                    e.Table.Invalidate(e.CellRect);

                    // check if the click started inside the button.  if
                    // it did, Raise the tables CellButtonClicked event
                    if (buttonRect.Contains(rendererData.ClickPoint))
                    {
                        e.Table.OnCellButtonClicked(new CellButtonEventArgs(e.Cell, e.Column, e.Row));
                    }
                }
                else
                {
                    // the mouse was released somewhere outside of the button,
                    // so make set the button back to its normal state
                    if (rendererData.ButtonState != PushButtonStates.Normal)
                    {
                        rendererData.ButtonState = PushButtonStates.Normal;

                        e.Table.Invalidate(e.CellRect);
                    }
                }
            }

            // reset the click point
            rendererData.ClickPoint = Point.Empty;
        }
        /// <summary>
        /// Raises the MouseDown event
        /// </summary>
        /// <param name="e">A CellMouseEventArgs that contains the event data</param>
        public override void OnMouseDown(CellMouseEventArgs e)
        {
            base.OnMouseDown(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            // check if the left mouse button is pressed
            if (e.Button == MouseButtons.Left)
            {
                // record where the click started
                rendererData.ClickPoint = new Point(e.X, e.Y);

                // if the click was inside the button, set the button state to pressed
                if (this.CalcButtonBounds().Contains(rendererData.ClickPoint))
                {
                    rendererData.ButtonState = PushButtonStates.Pressed;

                    e.Table.Invalidate(e.CellRect);
                }
            }
        }
        /// <summary>
        /// Raises the MouseMove event
        /// </summary>
        /// <param name="e">A CellMouseEventArgs that contains the event data</param>
        public override void OnMouseMove(CellMouseEventArgs e)
        {
            base.OnMouseMove(e);

            // get the button renderer data
            ButtonRendererData rendererData = this.GetButtonRendererData(e.Cell);

            Rectangle buttonRect = this.CalcButtonBounds();

            // check if the left mouse button is pressed
            if (e.Button == MouseButtons.Left)
            {
                // check if the mouse press originated in the button area
                if (buttonRect.Contains(rendererData.ClickPoint))
                {
                    // check if the mouse is currently in the button
                    if (buttonRect.Contains(e.X, e.Y))
                    {
                        // make sure the button is pressed
                        if (rendererData.ButtonState != PushButtonStates.Pressed)
                        {
                            rendererData.ButtonState = PushButtonStates.Pressed;

                            e.Table.Invalidate(e.CellRect);
                        }
                    }
                    else
                    {
                        // the mouse isn't inside the button so make sure it is "hot"
                        if (rendererData.ButtonState != PushButtonStates.Hot)
                        {
                            rendererData.ButtonState = PushButtonStates.Hot;

                            e.Table.Invalidate(e.CellRect);
                        }
                    }
                }
            }
            else
            {
                // check if the mouse is currently in the button
                if (buttonRect.Contains(e.X, e.Y))
                {
                    // the mouse is inside the button so make sure it is "hot"
                    if (rendererData.ButtonState != PushButtonStates.Hot)
                    {
                        rendererData.ButtonState = PushButtonStates.Hot;

                        e.Table.Invalidate(e.CellRect);
                    }
                }
                else
                {
                    // not inside the button so make sure it is in its normal state
                    if (rendererData.ButtonState != PushButtonStates.Normal)
                    {
                        rendererData.ButtonState = PushButtonStates.Normal;

                        e.Table.Invalidate(e.CellRect);
                    }
                }
            }
        }