using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.Media;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using DevComponents.DotNetBar.SuperGrid.Primitives;
using DevComponents.DotNetBar.SuperGrid.Style;
using DevComponents.SuperGrid.TextMarkup;
namespace DevComponents.DotNetBar.SuperGrid
{
    /// 
    /// Represents grid cell.
    /// 
    public class GridCell : GridElement, IComparable, IDisposable
    {
        #region Constants
        private const int CheckBoxSpacing = 3;
        #endregion
        #region Static variables
        private static CellInfoWindow _cellInfoWindow;
        private static CellArea _hitArea;
        private static CellArea _lastHitArea;
        private static GridCell _hitCell;
        private static CellArea _mouseDownHitArea;
        private static GridCell _mouseDownHitCell;
        private static Point _mouseDownPoint;
        private static IGridCellEditControl _mouseRenderer;
        private static bool _mouseInItem;
        private static bool _mouseDownInItem;
        private static bool _needsMouseEnter;
        private static bool _dragSelection;
        private static bool _dragStarted;
        private static int _anchorRowIndex;
        private static int _anchorColumnIndex;
        private static string _toolTipText;
        #endregion
        #region Private variables
        private int _ColumnIndex;
        private int _IndentLevel;
        private Size _CellSize;
        private Size _ContentSize;
        private Size _MeasuredSize;
        private Rectangle _Bounds;
        private Rectangle _BackBounds;
        private string _InfoText;
        private Image _InfoImage;
        private Cs _States;
        private EditorInfo _EditorInfo;
        private ushort _BoundsUpdateCount;
        private ushort _ColumnMeasureCount;
        private ushort _DataResetCount;
        private ushort _MergeUpdateCount;
        private ushort _RowMeasureCount;
        private ushort _SelectionClearCount;
        private ushort _SelectionUpdateCount;
        private ushort _StyleUpdateCount;
        private object _Value;
        private object _ExpValue;
        private CellVisualStyles _Styles;
        private CellVisualStyles _EffectiveStyles;
        #endregion
        #region Constructors
        ///
        /// GridCell
        ///
        public GridCell()
        {
            SetState(Cs.AllowEdit, true);
        }
        ///
        /// GridCell
        ///
        ///
        public GridCell(object value)
            : this()
        {
            _Value = value;
        }
        #endregion
        #region Internal properties
        #region AllowNullMerge
        internal bool AllowNullMerge
        {
            get
            {
                Tbool ns = GridColumn.AllowNullCellMerge;
                if (ns != Tbool.NotSet)
                    return (ns == Tbool.True ? true : false);
                return (GridPanel.AllowNullCellMerge);
            }
        }
        #endregion
        #region CanModify
        internal bool CanModify
        {
            get
            {
                GridColumn col = GridColumn;
                if (col == null || (col.AllowEdit == false || col.AllowSelection == false))
                    return (false);
                GridRow row = GridRow;
                if (row == null || (row.AllowEdit == false || row.AllowSelection == false || row.IsDeleted == true))
                    return (false);
                GridPanel panel = GridPanel;
                
                if (panel == null || (panel.AllowEdit == false || panel.AllowSelection == false))
                    return (false);
                if (Visible == false || AllowEdit == false ||
                    AllowSelection == false || IsEmptyCell == true || IsReadOnly == true)
                {
                    return (false);
                }
                return (true);
            }
        }
        #endregion
        #region CanModifyMerge
        internal bool CanModifyMerge
        {
            get
            {
                if (CanModify == false)
                    return (false);
                return (Merged == false || MergeSuspended == true);
            }
        }
        #endregion
        #region AnySelected
        internal bool AnySelected
        {
            get { return (TestState(Cs.AnySelected)); }
            set { SetState(Cs.AnySelected, value); }
        }
        #endregion
        #region CellSize
        internal Size CellSize
        {
            get { return (_CellSize); }
            set { _CellSize = value; }
        }
        #endregion
        #region CellEditMode
        internal CellEditMode CellEditMode
        {
            get
            {
                IGridCellEditControl editor = (EditControl ?? (GridColumn != null ? GridColumn.EditControl : null));
                if (editor == null)
                    editor = GetInternalEditControl();
                if (editor != null)
                    return (editor.CellEditMode);
                return (CellEditMode.InPlace);
            }
        }
        #endregion
        #region CheckBoxBounds
        internal Rectangle CheckBoxBounds
        {
            get { return (GridRow.CheckBoxBounds); }
        }
        #endregion
        #region ContentSize
        internal Size ContentSize
        {
            get { return(_ContentSize); }
        }
        #endregion
        #region RowContainer
        internal GridContainer RowContainer
        {
            get
            {
                GridRow row = GridRow;
                if (row != null)
                    return (row.Parent as GridContainer);
                return (null);
            }
        }
        #endregion
        #region HitArea
        internal CellArea HitArea
        {
            get { return (_hitArea); }
            set { _hitArea = value; }
        }
        #endregion
        #region IndentLevel
        internal int IndentLevel
        {
            get { return (_IndentLevel); }
            set { _IndentLevel = value; }
        }
        #endregion
        #region IsDragSelection
        internal bool IsDragSelection
        {
            get { return (_dragSelection); }
            set { _dragSelection = value; }
        }
        #endregion
        #region IsDragStarted
        internal bool IsDragStarted
        {
            get { return (_dragStarted); }
            set { _dragStarted = value; }
        }
        #endregion
        #region MergeUpdateCount
        internal ushort MergeUpdateCount
        {
            get { return (_MergeUpdateCount); }
            set { _MergeUpdateCount = value; }
        }
        #endregion
        #region MeasuredSize
        internal Size MeasuredSize
        {
            get { return (_MeasuredSize); }
        }
        #endregion
        #region Modified
        internal bool Modified
        {
            get { return (TestState(Cs.Modified)); }
            set { SetState(Cs.Modified, value); }
        }
        #endregion
        #region MouseRenderer
        internal IGridCellEditControl MouseRenderer
        {
            get { return (_mouseRenderer); }
            set { _mouseRenderer = value; }
        }
        #endregion
        #region NeedsMeasured
        internal override bool NeedsMeasured
        {
            get
            {
                if (_ColumnMeasureCount != GridColumn.MeasureCount)
                    return (true);
                if (_RowMeasureCount != GridRow.MeasureCount)
                    return (true);
                return (base.NeedsMeasured);
            }
            set
            {
                if (value == false)
                {
                    _ColumnMeasureCount = GridColumn.MeasureCount;
                    _RowMeasureCount = GridRow.MeasureCount;
                }
                base.NeedsMeasured = value;
            }
        }
        #endregion
        #region Selected
        internal bool Selected
        {
            get
            {
                if (AllowSelection == false)
                    return (false);
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    if (_SelectionClearCount != panel.SelectionClearCount)
                    {
                        _SelectionClearCount = panel.SelectionClearCount;
                        Selected = false;
                        if (GridRow.ExpandedVisible(panel) == true)
                            panel.SetSelectedEx(this, false);
                        InvalidateRender();
                    }
                }
                return (TestState(Cs.Selected));
            }
            set
            {
                SetState(Cs.Selected, value);
                GridPanel panel = GridPanel;
                if (panel != null)
                    _SelectionClearCount = panel.SelectionClearCount;
            }
        }
        #endregion
        #region SelectionUpdateCount
        internal ushort SelectionUpdateCount
        {
            get { return (_SelectionUpdateCount); }
            set { _SelectionUpdateCount = value; }
        }
        #endregion
        #region ValueEx
        internal object ValueEx
        {
            get { return (_Value); }
            set
            {
                if ((value != null && value.Equals(_Value) == false) ||
                    (value == null && _Value != null))
                {
                    object oldValue = _Value;
                    _Value = value;
                     OnValueChanged(oldValue, value, DataContext.CellValueLoad);
                }
            }
        }
        #endregion
        #region ValueExx
        internal object ValueExx
        {
            get { return (_Value); }
            set { _Value = value; }
        }
        #endregion
        #endregion
        #region Public properties
        #region AllowEdit
        /// 
        /// Gets or sets whether the cell can be edited by the user. 
        /// 
        [DefaultValue(true), Category("Behavior")]
        [Description("Indicates whether the cell can be edited by the user.")]
        public bool AllowEdit
        {
            get { return (TestState(Cs.AllowEdit)); }
            set
            {
                if (value != AllowEdit)
                {
                    SetState(Cs.AllowEdit, value);
                    OnPropertyChanged("AllowEdit");
                }
            }
        }
        #endregion
        #region BackBounds
        ///
        /// Gets the scroll adjusted background bounds of the cell
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle BackBounds
        {
            get
            {
                if (_BoundsUpdateCount != SuperGrid.BoundsUpdateCount)
                    UpdateBoundingRects();
                return (_BackBounds);
            }
        }
        #endregion
        #region Bounds
        ///
        /// Gets the scroll adjusted bounds of the cell
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Rectangle Bounds
        {
            get
            {
                if (_BoundsUpdateCount != SuperGrid.BoundsUpdateCount)
                    UpdateBoundingRects();
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    CellRange cr = GetStateCellRange();
                    if (cr != null)
                        return (GetBounds(panel, cr.BackBounds));
                }
                return (_Bounds);
            }
        }
        #endregion
        #region BoundsRelative
        /// 
        /// Gets or sets the relative bounds of the cell
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Rectangle BoundsRelative
        {
            get { return (base.BoundsRelative); }
            internal set
            {
                base.BoundsRelative = value;
                _BoundsUpdateCount = 0;
            }
        }
        #endregion
        #region CellBounds
        ///
        /// Gets the clipped, scroll adjusted, bounding rectangle of the cell 
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle CellBounds
        {
            get
            {
                if (_BoundsUpdateCount != SuperGrid.BoundsUpdateCount)
                    UpdateBoundingRects();
                GridPanel panel = GridPanel;
                if (panel != null)
                    return (GetCellBounds(panel));
                return (Bounds);
            }
        }
        #endregion
        #region CellStyles
        /// 
        /// Gets or sets the visual styles assigned to the cell
        /// 
        [Category("Style")]
        [Description("Indicates the visual styles assigned to the cell.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public CellVisualStyles CellStyles
        {
            get
            {
                if (_Styles == null)
                {
                    _Styles = new CellVisualStyles();
                    StyleVisualChangeHandler(null, _Styles);
                }
                return (_Styles);
            }
            set
            {
                if (_Styles != value)
                {
                    CellVisualStyles oldValue = _Styles;
                    _Styles = value;
                    OnCellStyleChanged("CellVisualStyles", oldValue, value);
                    if (oldValue != null)
                        oldValue.Dispose();
                }
            }
        }
        private void OnCellStyleChanged(string property,
            CellVisualStyles oldValue, CellVisualStyles newValue)
        {
            StyleVisualChangeHandler(oldValue, newValue);
            OnPropertyChanged(property);
        }
        #endregion
        #region ColumnIndex
        /// 
        /// Gets the associated Column index for the cell
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ColumnIndex
        {
            get { return (_ColumnIndex); }
            internal set { _ColumnIndex = value; }
        }
        #endregion
        #region ContentBounds
        ///
        /// Gets the scroll adjusted, content only, bounding rectangle of the cell 
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle ContentBounds
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                    return (GetContentBounds(panel));
                return (Rectangle.Empty);
            }
        }
        #endregion
        #region EditBounds
        ///
        /// Gets the clipped, scroll adjusted, edit bounding rectangle of the cell 
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle EditBounds
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                    return (GetEditBounds(panel));
                return (Rectangle.Empty);
            }
        }
        #endregion
        #region EditControl
        ///
        /// Gets the Edit Control used for the cell. The cell level
        /// edit control is a non-shared control, created and based
        /// upon the cell level EditorType and EditorParams properties.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IGridCellEditControl EditControl
        {
            get
            {
                if (_EditorInfo == null || _EditorInfo.EditorType == null)
                    return (null);
                if (_EditorInfo.EditControl == null)
                    EditControl = GetEditControl(_EditorInfo.EditorType, _EditorInfo.EditorParams);
                return (_EditorInfo.EditControl);
            }
            internal set
            {
                if (_EditorInfo == null)
                    _EditorInfo = new EditorInfo();
                if (_EditorInfo.EditControl != value)
                {
                    if (_EditorInfo.EditControl != null)
                    {
                        if (_EditorInfo.EditControl.EditorPanel.Parent != null)
                            SuperGrid.Controls.Remove(_EditorInfo.EditControl.EditorPanel);
                        _EditorInfo.EditControl.EditorCellBitmap = null;
                        if (_EditorInfo.EditorType != null)
                            ((Control)_EditorInfo.EditControl).Dispose();
                    }
                    _EditorInfo.EditControl = value;
                    if (_EditorInfo.EditControl != null)
                    {
                        if (_EditorInfo.EditControl.EditorPanel.Parent == null)
                            SuperGrid.Controls.Add(_EditorInfo.EditControl.EditorPanel);
                    }
                }
            }
        }
        #endregion
        #region EditorDirty
        ///
        /// Gets or sets whether the value
        /// being edited has been changed in the editor 
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool EditorDirty
        {
            get { return (GridRow.EditorDirty); }
            set
            {
                GridRow.EditorDirty = value;
                // If it is a non-modal edit event then we want the
                // editor's dirty state to be cleared immediately.
                if (SuperGrid.EditorActive == false)
                    GridRow.EditorDirty = false;
            }
        }
        #endregion
        #region EditorParams
        /// 
        /// Gets or sets an array of arguments that match in number,
        /// order, and type the parameters of the EditControl constructor
        /// to invoke. If empty or null, the default constructor is invoked.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object[] EditorParams
        {
            get
            {
                if (_EditorInfo == null)
                    return (null);
                return (_EditorInfo.EditorParams);
            }
            set
            {
                if (_EditorInfo == null)
                    _EditorInfo = new EditorInfo();
                if (IsSameParams(_EditorInfo.EditorParams, value) == false)
                {
                    _EditorInfo.EditorParams = value;
                    EditControl = null;
                    RenderControl = null;
                    NeedsMeasured = true;
                    OnPropertyChangedEx("EditorParams", VisualChangeType.Layout);
                }
                                    
                if (_EditorInfo.IsEmpty == true)
                    _EditorInfo = null;
            }
        }
        #region IsSameParams
        private bool IsSameParams(object[] p1, object[] p2)
        {
            if (p1 == null || p2 == null)
                return (p1 == p2);
            if (p1.Length != p2.Length)
                return (false);
            for (int i = 0; i < p1.Length; i++)
            {
                if (p1[i] != p2[i])
                    return (false);
            }
            return (true);
        }
        #endregion
        #endregion
        #region EditorType
        ///
        /// Indicates the cell editor type. This is the control type
        /// used to perform the actual modification of the cell value
        ///
        [DefaultValue(null), Category("Data")]
        [Description("Indicates the cell editor type. This is the control type used to perform the actual modification of the cell value.")]
        [TypeConverter(typeof(EditTypeConverter))]
        [Editor("DevComponents.SuperGrid.Design.EditTypeEditor, DevComponents.SuperGrid.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=26d81176cfa2b486", typeof(UITypeEditor))]
        public Type EditorType
        {
            get
            {
                if (_EditorInfo == null)
                    return (null);
                return (_EditorInfo.EditorType);
            }
            set
            {
                if (value != null || _EditorInfo != null)
                {
                    if (_EditorInfo == null)
                        _EditorInfo = new EditorInfo();
                    if (_EditorInfo.EditorType != value)
                    {
                        _EditorInfo.EditorType = value;
                        _EditorInfo.EditControl = null;
                        _EditorInfo.RenderControl = null;
                        NeedsMeasured = true;
                        OnPropertyChangedEx("EditorType", VisualChangeType.Layout);
                    }
                    if (_EditorInfo.IsEmpty == true)
                        _EditorInfo = null;
                }
            }
        }
        #endregion
        #region ExpValue
        ///
        /// Gets the last evaluated expression value for the cell.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object ExpValue
        {
            get { return (_ExpValue); }
        }
        #endregion
        #region FormattedValue
        /// 
        /// Gets the associated Formatted Value for the cell
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string FormattedValue
        {
            get { return (GetFormattedValue()); }
        }
        #endregion
        #region GridColumn
        /// 
        /// Gets the GridColumn associated with the cell
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GridColumn GridColumn
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel == null && GridRow != null)
                    panel = GridRow.AllocPanel;
                if (panel != null)
                {
                    if (_ColumnIndex < panel.Columns.Count)
                        return (panel.Columns[_ColumnIndex]);
                }
                return (null);
            }
        }
        #endregion
        #region GridRow
        ///
        /// Gets the GridRow associated with the cell.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public GridRow GridRow
        {
            get { return (Parent as GridRow); }
        }
        #endregion
        #region HighLightBounds
        ///
        /// Gets the scroll adjusted, bounding rectangle used
        /// to highlight the cell contents when selected.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle HighLightBounds
        {
            get
            {
                Rectangle r = Rectangle.Empty;
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    switch (GetCellHighlightMode(panel))
                    {
                        case CellHighlightMode.Content:
                            IGridCellEditControl editor = GetInternalRenderControl();
                            r = GetAdjustedBounds(ContentBounds);
                            r = GetEditPanelBounds(editor, r);
                            r.Inflate(1, 1);
                            break;
                        case CellHighlightMode.Partial:
                            r = GetAdjustedBounds(ContentBounds);
                            r.Inflate(1, 1);
                            break;
                        case CellHighlightMode.Full:
                            r = GetAdjustedBounds();
                            Rectangle t = SViewRect;
                            if (t.X == 0 && r.X == 0)
                            {
                                r.X += Dpi.Width1;
                                r.Width -= Dpi.Width1;
                            }
                            break;
                    }
                }
                return (r);
            }
        }
        #endregion
        #region InfoImage
        /// 
        /// Gets or sets the cell informational Image (the image
        /// to display when InfoText is non-empty)
        /// 
        [DefaultValue(null), Category("Appearance")]
        [Description("Indicates the cell informational Image (the image to display when InfoText is non-empty).")]
        public Image InfoImage
        {
            get { return (_InfoImage); }
            set
            {
                if (_InfoImage != value)
                {
                    _InfoImage = value;
                    OnPropertyChangedEx("InfoImage", VisualChangeType.Render);
                }
            }
        }
        #region GetInfoImage
        internal Image GetInfoImage()
        {
            return (_InfoImage ?? GridColumn.GetInfoImage());
        }
        #endregion
        #endregion
        #region InfoImageBounds
        ///
        /// Gets the scroll adjusted, bounding
        /// rectangle for the current set info image
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle InfoImageBounds
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    Image image = GetInfoImage();
                    if (image != null)
                    {
                        if (ShowInfoCellImage(panel) == true)
                        {
                            Rectangle r = GetAdjustedBounds(ContentBounds);
                            r.Inflate(-2, -1);
                            Rectangle t = r;
                            switch (GridColumn.InfoImageAlignment)
                            {
                                case Alignment.TopCenter:
                                    r.X += (r.Width - image.Width) / 2;
                                    break;
                                case Alignment.TopRight:
                                    r.X = (r.Right - image.Width);
                                    break;
                                case Alignment.MiddleLeft:
                                    if (GridColumn.InfoImageOverlay == false)
                                        r.X -= (image.Width + 4);
                                    r.Y += (r.Height - image.Height) / 2;
                                    break;
                                case Alignment.MiddleCenter:
                                    r.X += (r.Width - image.Width) / 2;
                                    r.Y += (r.Height - image.Height) / 2;
                                    break;
                                case Alignment.MiddleRight:
                                    r.X = (GridColumn.InfoImageOverlay == true)
                                        ? (r.Right - image.Width) : (r.Right + 4);
                                    r.Y += (r.Height - image.Height) / 2;
                                    break;
                                case Alignment.BottomLeft:
                                    r.Y = (r.Bottom - image.Height);
                                    break;
                                case Alignment.BottomCenter:
                                    r.X += (r.Width - image.Width) / 2;
                                    r.Y = (r.Bottom - image.Height);
                                    break;
                                case Alignment.BottomRight:
                                    r.X = (r.Right - image.Width);
                                    r.Y = (r.Bottom - image.Height);
                                    break;
                            }
                            if (r.Y < t.Y)
                                r.Y = t.Y;
                            r.Width = image.Width;
                            r.Height = image.Height;
                            return (r);
                        }
                    }
                }
                return (Rectangle.Empty);
            }
        }
        #endregion
        #region InfoText
        ///
        /// Gets or sets the informational text associated with
        /// the cell.  If the InfoText is non-null, then the cells
        /// associated InfoImage is displayed in the cell, with the
        /// InfoText being displayed as the ToolTip for the InfoImage.
        ///
        [DefaultValue(null), Category("Appearance")]
        [Description("Indicates the informational text associated with the cell. If the InfoText is non-null, then the cells associated InfoImage is displayed in the cell, with the InfoText being displayed as the ToolTip for the InfoImage.")]
        public string InfoText
        {
            get { return (_InfoText); }
            set
            {
                if (_InfoText != value)
                {
                    _InfoText = value;
                    UpdateInfoWindow();
                    OnPropertyChangedEx("InfoText", VisualChangeType.Render);
                }
            }
        }
        #endregion
        #region IsActiveCell
        ///
        /// Gets whether the cell is the Active cell.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsActiveCell
        {
            get
            {
                if (SuperGrid != null)
                    return (SuperGrid.ActiveCell == this);
                return(false);
            }
        }
        #endregion
        #region IsCellVisible
        ///
        /// Gets whether the cell is visible (taking row visibility,
        /// column visibility, and expanded row state into account).
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsCellVisible
        {
            get
            {
                if (BoundsRelative.Width > 0)
                {
                    GridRow row = GridRow;
                    if (row != null)
                    {
                        if (GridColumn.Visible == false)
                            return (false);
                        return (row.IsExpandedVisible);
                    }
                }
                return (false);
            }
        }
        #endregion
        #region IsDataError
        ///
        /// Gets whether setting the cell Value has caused a Data Error
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsDataError
        {
            get { return (TestState(Cs.DataError)); }
            internal set { SetState(Cs.DataError, value); }
        }
        #endregion
        #region IsEditorCell
        ///
        /// Gets whether the cell is the cell being edited.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsEditorCell
        {
            get
            {
                if (SuperGrid != null)
                    return (SuperGrid.EditorCell == this);
                return (false);
            }
        }
        #endregion
        #region IsEmptyCell
        ///
        /// Gets whether the cell is an Empty cell.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsEmptyCell
        {
            get { return (TestState(Cs.EmptyCell)); }
            internal set { SetState(Cs.EmptyCell, value); }
        }
        #endregion
        #region IsHFrozen
        ///
        /// Gets whether the cell is horizontally frozen
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsHFrozen
        {
            get
            {
                GridColumn column = GridColumn;
                if (column != null)
                    return (column.IsHFrozen);
                return (false);
            }
        }
        #endregion
        #region IsPrimaryCell
        ///
        /// Gets whether the cell is the defined PrimaryCell
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsPrimaryCell
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                    return (panel.PrimaryColumnIndex == _ColumnIndex);
                return (false);
            }
        }
        #endregion
        #region IsReadOnly
        ///
        /// Gets whether the cell is ReadOnly due to 
        /// row, column, or cell ReadOnly property status.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsReadOnly
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    if (panel.ReadOnly || GridColumn.ReadOnly || GridRow.ReadOnly)
                        return (true);
                }
                return (TestState(Cs.ReadOnly));
            }
        }
        #endregion
        #region IsSelectable
        ///
        /// Gets whether the cell is selectable due to
        /// row, column, or cell AllowSelection property status.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsSelectable
        {
            get
            {
                return (AllowSelection == true &&
                    GridRow.AllowSelection == true &&
                    GridColumn.AllowSelection == true);
            }
        }
        #endregion
        #region IsSelected
        ///
        /// Gets or sets whether the cell is selected.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsSelected
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    if (AllowSelection == true && panel.AllowSelection == true)
                    {
                        if (_SelectionUpdateCount != panel.SelectionUpdateCount)
                        {
                            _SelectionUpdateCount = panel.SelectionUpdateCount;
                            AnySelected = false;
                            if (GridRow != null && GridColumn != null)
                            {
                                if (GridRow.IsSelected == true || GridColumn.IsSelected == true)
                                {
                                    AnySelected = true;
                                }
                                else
                                {
                                    CellRange cr = GetCellRange();
                                    if (cr != null && cr.Suspended == false)
                                    {
                                        AnySelected = cr.IsSelected(panel, RowContainer);
                                    }
                                    else
                                    {
                                        if (GridRow.ExpandedVisible(panel) == true)
                                            Selected = panel.IsItemSelectedEx(this);
                                        AnySelected = Selected;
                                    }
                                }
                            }
                        }
                        return (AnySelected);
                    }
                }
                return (false);
            }
            set
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    if (Selected != value)
                    {
                        Selected = value;
                        if (GridRow != null)
                        {
                            if (GridRow.ExpandedVisible(panel) == true)
                                panel.SetSelectedEx(this, value);
                            if (value == true)
                            {
                                AnySelected = true;
                                _SelectionUpdateCount = panel.SelectionUpdateCount;
                            }
                            InvalidateRender();
                        }
                    }
                }
            }
        }
        #endregion
        #region IsValueExpression
        ///
        /// Gets whether the cell Value is an expression.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsValueExpression
        {
            get { return (TestState(Cs.ValueExpression)); }
            internal set { SetState(Cs.ValueExpression, value); }
        }
        #endregion
        #region IsValueNull
        ///
        /// Gets whether the cell Value is null.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsValueNull
        {
            get
            {
                object value = Value;
                return (((GridPanel != null && GridPanel.NullValue == NullValue.DBNull)
                    ? DBNull.Value : null) == value);
            }
        }
        #endregion
        #region Merged
        ///
        ///Gets whether the cell is merged
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool Merged
        {
            get { return (TestState(Cs.Merged)); }
            internal set
            {
                if (value != Merged)
                {
                    SetState(Cs.Merged, value);
                    ClearEffectiveStyles();
                    if (value == true && _mouseDownHitCell == this)
                        DoRendererMouseLeave(EventArgs.Empty);
                }
            }
        }
        #endregion
        #region MergedBottom
        ///
        ///Gets or sets whether the cell is Merged at the Bottom
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool MergedBottom
        {
            get { return (TestState(Cs.MergedBottom)); }
            set { SetState(Cs.MergedBottom, value); }
        }
        #endregion
        #region MergedLeft
        ///
        ///Gets or sets whether the cell is Merged to the Left
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool MergedLeft
        {
            get { return (TestState(Cs.MergedLeft)); }
            set { SetState(Cs.MergedLeft, value); }
        }
        #endregion
        #region MergedRight
        ///
        ///Gets or sets whether the cell is Merged to the Right
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool MergedRight
        {
            get { return (TestState(Cs.MergedRight)); }
            set { SetState(Cs.MergedRight, value); }
        }
        #endregion
        #region MergedTop
        ///
        ///Gets or sets whether the cell is Merged at the Top
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool MergedTop
        {
            get { return (TestState(Cs.MergedTop)); }
            set { SetState(Cs.MergedTop, value); }
        }
        #endregion
        #region MergeSuspended
        ///
        ///Gets whether the cell is merged and suspended.
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool MergeSuspended
        {
            get
            {
                CellRange cr = GetCellRange();
                return (cr != null && cr.Suspended == true);
            }
        }
        #endregion
        #region NullString
        /// 
        /// Gets how null values are displayed 
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string NullString
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                    return (GridColumn.NullString ?? panel.NullString);
                return (String.Empty);
            }
        }
        #endregion
        #region ReadOnly
        /// 
        /// Gets or sets whether the user can change cell contents
        /// 
        [DefaultValue(false), Category("Behavior")]
        [Description("Indicates whether the user can change cell contents.")]
        public bool ReadOnly
        {
            get { return (TestState(Cs.ReadOnly)); }
            set
            {
                if (value != ReadOnly)
                {
                    SetState(Cs.ReadOnly, value);
                    OnPropertyChangedEx("ReadOnly", VisualChangeType.Render);
                }
            }
        }
        #endregion
        #region RenderControl
        ///
        /// Gets the current set Render Control for the cell
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IGridCellEditControl RenderControl
        {
            get
            {                    
                if (_EditorInfo == null ||
                    (_EditorInfo.RenderType == null && _EditorInfo.EditorType == null))
                {
                    return (null);
                }
                if (_EditorInfo.RenderControl == null)
                {
                    RenderControl = (_EditorInfo.RenderType != null)
                                        ? GetEditControl(_EditorInfo.RenderType, _EditorInfo.RenderParams)
                                        : GetEditControl(_EditorInfo.EditorType, _EditorInfo.EditorParams);
                }
                return (_EditorInfo.RenderControl);
            }
            internal set
            {
                if (_EditorInfo == null)
                    _EditorInfo = new EditorInfo();
                if (_EditorInfo.RenderControl != value)
                {
                    if (_EditorInfo.RenderControl != null)
                    {
                        if (_EditorInfo.RenderControl.EditorPanel.Parent != null)
                            SuperGrid.Controls.Remove(_EditorInfo.RenderControl.EditorPanel);
                        _EditorInfo.RenderControl.EditorCellBitmap = null;
                        if (_EditorInfo.RenderType != null || _EditorInfo.EditorType != null)
                            ((Control)_EditorInfo.RenderControl).Dispose();
                    }
                    _EditorInfo.RenderControl = value;
                    if (_EditorInfo.RenderControl != null)
                    {
                        if (_EditorInfo.RenderControl.EditorPanel.Parent == null)
                            SuperGrid.Controls.Add(_EditorInfo.RenderControl.EditorPanel);
                    }
                }
            }
        }
        #endregion
        #region RenderParams
        /// 
        /// Gets or sets an array of arguments that match in number,
        /// order, and type the parameters of the RenderControl constructor
        /// to invoke. If empty or null, the default constructor is invoked.
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object[] RenderParams
        {
            get
            {
                if (_EditorInfo == null)
                    return (null);
                return (_EditorInfo.RenderParams);
            }
            set
            {
                if (_EditorInfo == null)
                    _EditorInfo = new EditorInfo();
                if (IsSameParams(_EditorInfo.RenderParams, value) == false)
                {
                    _EditorInfo.RenderParams = value;
                    RenderControl = null;
                    NeedsMeasured = true;
                    OnPropertyChangedEx("RenderParams", VisualChangeType.Layout);
                }
                if (_EditorInfo.IsEmpty == true)
                    _EditorInfo = null;
            }
        }
        #endregion
        #region RenderType
        ///
        /// Gets or sets the cell render type. This is the control
        /// type used to perform the default rendering of the cell value
        ///
        [DefaultValue(null), Category("Data")]
        [Description("Indicates the cell render type. This is the control type used to perform the default rendering of the cell value.")]
        [TypeConverter(typeof(EditTypeConverter))]
        [Editor("DevComponents.SuperGrid.Design.EditTypeEditor, DevComponents.SuperGrid.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=26d81176cfa2b486", typeof(UITypeEditor))]
        public Type RenderType
        {
            get
            {
                if (_EditorInfo == null)
                    return (null);
                return (_EditorInfo.RenderType);
            }
            set
            {
                if (value != null || _EditorInfo != null)
                {
                    if (_EditorInfo == null)
                        _EditorInfo = new EditorInfo();
                    if (_EditorInfo.RenderType != value)
                    {
                        _EditorInfo.RenderType = value;
                        _EditorInfo.RenderControl = null;
                        NeedsMeasured = true;
                        OnPropertyChangedEx("RenderType", VisualChangeType.Layout);
                    }
                    if (_EditorInfo.IsEmpty == true)
                        _EditorInfo = null;
                }
            }
        }
        #endregion
        #region RowIndex
        /// 
        /// Gets the associated Row index for the cell
        /// 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int RowIndex
        {
            get
            {
                GridRow row = GridRow;
                return (row != null ? row.RowIndex : -1);
            }
        }
        #endregion
        #region UnMergedBounds
        ///
        /// Gets the scroll adjusted un-merged bounds of the cell
        ///
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Rectangle UnMergedBounds
        {
            get
            {
                if (_BoundsUpdateCount != SuperGrid.BoundsUpdateCount)
                    UpdateBoundingRects();
                return (_Bounds);
            }
        }
        #endregion
        #region Value
        /// 
        /// Gets or sets the cell value
        /// 
        [DefaultValue(null), Category("Data")]
        [Description("Indicates the cell value.")]
        [TypeConverter(typeof(ValueTypeConverter))]
        [Editor("DevComponents.SuperGrid.Design.ValueTypeEditor, DevComponents.SuperGrid.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=26d81176cfa2b486", typeof(UITypeEditor))]
        public object Value
        {
            get
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    object o = GetValue(panel);
                    if (SuperGrid != null)
                        SuperGrid.DoGetCellValueEvent(this, ref o);
                    return (o);
                }
                return (_Value);
            }
            set
            {
                if ((value != null && value.Equals(_Value) == false) ||
                    (value == null && _Value != null))
                {
                    object oldValue = _Value;
                    SetValue(value);
                    GridRow row = GridRow;
                    if (row != null && row.Loading == false)
                        OnValueChanged(oldValue, value, DataContext.CellEdit);
                }
            }
        }
        #region GetValue
        /// 
        /// GetValue
        /// 
        /// 
        /// 
        protected virtual object GetValue(GridPanel panel)
        {
            if (panel.DataSource != null)
            {
                if (ActiveIList(panel) == true ||
                    _DataResetCount != panel.DataBinder.DataResetCount)
                {
                    _DataResetCount = panel.DataBinder.DataResetCount;
                    object o = panel.DataBinder.GetValue(this, _Value);
                    if ((o == null && o != _Value) ||
                        (o != null && o.Equals(_Value) == false))
                    {
                        _Value = o;
                        GridColumn.NeedsFilterScan = true;
                        InvalidateRender();
                        return (o);
                    }
                }
            }
            return (_Value);
        }
        #region ActiveIList
        private bool ActiveIList(GridPanel panel)
        {
            if (panel.DataSource is IList &&
                (panel.DataSource is IListSource == false &&
                 panel.DataSource is IBindingList == false))
            {
                GridRow row = GridRow;
                if (row != null)
                {
                    if (panel.LatentActiveRowIndex < 0 && row.IsTempInsertRow == false)
                        return (true);
                }
            }
            return (false);
        }
        #endregion
        #endregion
        #region SetValue
        /// 
        /// SetValue
        /// 
        /// 
        protected virtual void SetValue(object value)
        {
            _Value = value;
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                GridRow row = GridRow;
                if (row.Loading == false && IsLoading() == false)
                {
                    GridColumn column = GridColumn;
                    panel.DataBinder.SetValue(this, value);
                    row.RowNeedsStored = true;
                    column.NeedsFilterScan = true;
                    if (column.IsGroupColumn == true)
                    {
                        if (row == panel.ActiveRow)
                            row.RowNeedsGrouped = true;
                        else
                            panel.NeedsGrouped = true;
                    }
                    if (panel.KeepRowsSorted == true)
                    {
                        if (column.IsSortColumn == true)
                        {
                            if (row.IsTempInsertRow == false)
                            {
                                if (row == panel.ActiveRow)
                                    row.RowNeedsSorted = true;
                                else
                                    panel.NeedsSorted = true;
                            }
                        }
                    }
                }
            }
        }
        private bool IsLoading()
        {
            SuperGridControl sg = SuperGrid;
            return (sg == null || sg.Parent == null);
        }
        #endregion
        #region OnValueChanged
        private void OnValueChanged(object oldValue, object newValue, DataContext context)
        {
            NeedsMeasured = true;
            IsDataError = false;
            ClearEffectiveStyles();
            if (GridRow.Loading == false)
                RefreshCellEditor();
            OnPropertyChanged("Value");
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                SuperGrid.DoCellValueChangedEvent(this, oldValue, newValue, context);
                if (panel.EnableCellExpressions == true)
                {
                    if (GridRow.Loading == false)
                        UpdateCellExp(panel, oldValue, newValue);
                }
                UpdateMerge(panel);
            }
        }
        #region RefreshCellEditor
        private void RefreshCellEditor()
        {
            if (SuperGrid != null)
            {
                IGridCellEditControl editor = GetInternalEditControl(true);
                if (editor != null)
                {
                    if (SuperGrid.NonModalEditorCell == this)
                        RefreshNonModalEditor();
                    else if (SuperGrid.EditorCell == this)
                        RefreshEditor(editor);
                    switch (editor.ValueChangeBehavior)
                    {
                        case ValueChangeBehavior.InvalidateLayout:
                            GridColumn.NeedsResized = true;
                            GridRow.NeedsMeasured = true;
                            InvalidateLayout();
                            break;
                        default:
                            InvalidateRender();
                            break;
                    }
                }
            }
        }
        #region RefreshEditor
        private void RefreshEditor(IGridCellEditControl editor)
        {
            editor.SuspendUpdate = true;
            try
            {
                CellVisualStyle style = GetEffectiveStyle();
                editor.InitializeContext(this, style);
            }
            finally
            {
                editor.SuspendUpdate = false;
            }
        }
        #endregion
        #region RefreshNonModalEditor
        private void RefreshNonModalEditor()
        {
            if (SuperGrid.ActiveNonModalEditor != null)
            {
                SuperGrid.ActiveNonModalEditor.EditorValue = _Value;
                CellVisualStyle style = GetEffectiveStyle();
                InitializeContext(DataContext.CellValueLoad,
                    SuperGrid.ActiveNonModalEditor, style);
            }
        }
        #endregion
        #endregion
        #region UpdateMerge
        private void UpdateMerge(GridPanel panel)
        {
            CellRange cr = GetCellRange();
            if (cr != null && cr.Suspended == true)
            {
                Modified = true;
                cr.Modified = true;
            }
            else
            {
                if (CellCanMerge(panel) == true)
                {
                    MergeUpdateCount--;
                    if (RowContainer.IsMergeSuspended == true)
                        RowContainer.MergeUpdateCount++;
                    RowContainer.NeedMergeLayout = true;
                    RowContainer.InvalidateLayout();
                }
            }
        }
        #region CellCanMerge
        private bool CellCanMerge(GridPanel panel)
        {
            if (panel != null && panel.EnableCellMerging == true)
            {
                CellMergeMode cMode = GridColumn.CellMergeMode;
                if (cMode == CellMergeMode.NotSet)
                    cMode = panel.CellMergeMode;
                return (cMode != CellMergeMode.None);
            }
            return (false);
        }
        #endregion
        #endregion
        #endregion
        #region UpdateCellExp
        internal void UpdateCellExp(
            GridPanel panel, object oldValue, object value)
        {
            string oldExp = oldValue as string;
            string newExp = value as string;
            if (oldExp != null)
            {
                oldExp = oldExp.Trim();
                if (oldExp.StartsWith("="))
                {
                    panel.ExpDictionary.Remove(this);
                    InfoText = null;
                }
            }
            IsValueExpression = false;
            if (newExp != null)
            {
                newExp = newExp.Trim();
                if (newExp.StartsWith("="))
                    SetCellExp(panel, newExp);
            }
            RefreshExpressions(panel, this, new List());
        }
        #region RefreshExpressions
        private void RefreshExpressions(
            GridPanel panel, GridCell gridCell, List usedCells)
        {
            foreach (KeyValuePair item in panel.ExpDictionary)
            {
                List cells = item.Value.GetCellReferences();
                if (cells != null)
                {
                    if (cells.Contains(gridCell) == true)
                    {
                        item.Key.InvalidateRender();
                        if (usedCells.Contains(item.Key) == false)
                        {
                            usedCells.Add(item.Key);
                            RefreshExpressions(panel, item.Key, usedCells);
                            usedCells.Remove(item.Key);
                        }
                    }
                }
            }
        }
        #endregion
        #region SetCellExp
        internal void SetCellExp(GridPanel panel, string newExp)
        {
            if (panel.EnableCellExpressions == true)
            {
                IsValueExpression = false;
                while (true)
                {
                    try
                    {
                        EEval eval = new EEval(this, newExp);
                        panel.ExpDictionary[this] = eval;
                        InfoText = null;
                        IsValueExpression = true;
                        break;
                    }
                    catch (Exception exp)
                    {
                        bool retry = false;
                        bool throwException = false;
                        if (SuperGrid.HasDataErrorHandler == true)
                        {
                            object value = newExp;
                            if (SuperGrid.DoDataErrorEvent(GridPanel, this, exp,
                                DataContext.CellExpressionParse, ref value, ref throwException, ref retry) == true)
                            {
                                return;
                            }
                        }
                        if (throwException == true)
                            throw;
                        InfoText = exp.Message;
                        if (retry == false)
                            break;
                    }
                }
            }
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #region TestState
        private bool TestState(Cs state)
        {
            return ((_States & state) == state);
        }
        #endregion
        #region SetState
        private void SetState(Cs state, bool value)
        {
            if (value == true)
                _States |= state;
            else
                _States &= ~state;
        }
        #endregion
        #region MeasureOverride
        //private int _MeasureCount;
        /// 
        /// Performs the layout of the item and sets
        /// the Size property to size that item will take.
        /// 
        /// Layout information.
        /// 
        /// 
        protected override void MeasureOverride(
            GridLayoutInfo layoutInfo, GridLayoutStateInfo stateInfo, Size constraintSize)
        {
           //_MeasureCount++;
            MeasureCell(layoutInfo.Graphics,
                stateInfo.GridPanel, stateInfo.IndentLevel, constraintSize);
        }
        #region MeasureCell
        private void MeasureCell(Graphics g,
            GridPanel panel, int indentLevel, Size constraintSize)
        {
            Size sizeNeeded = Size.Empty;
            if (ColumnIndex < panel.Columns.Count)
            {
                CellVisualStyle style = GetSizingStyle(panel);
                Size imageSize = style.GetFigureSize(panel);
                Alignment imageAlignment = style.ImageAlignment;
                if (style.IsOverlayImage == true)
                    imageAlignment = Alignment.MiddleCenter;
                int width = constraintSize.Width;
                Size borderSize = style.GetBorderSize(true);
                int bwidth = borderSize.Width + Dpi.Width2;
                int bheight = borderSize.Height + Dpi.Height2;
                if (constraintSize.Width > 1)
                {
                    switch (imageAlignment)
                    {
                        case Alignment.TopCenter:
                        case Alignment.MiddleCenter:
                        case Alignment.BottomCenter:
                            break;
                        default:
                            width -= imageSize.Width;
                            break;
                    }
                    width -= bwidth;
                    if (BoundsRelative.X == GridPanel.Bounds.X)
                        width -= Dpi.Width1;
                }
                _ContentSize =
                    GetProposedSize(g, style, new Size(width, 0));
                switch (imageAlignment)
                {
                    case Alignment.MiddleCenter:
                        sizeNeeded.Height = Math.Max(imageSize.Height, _ContentSize.Height) + bheight;
                        sizeNeeded.Width = Math.Max(_ContentSize.Width, imageSize.Width) + bwidth;
                        break;
                    case Alignment.TopCenter:
                    case Alignment.BottomCenter:
                        sizeNeeded.Width = Math.Max(_ContentSize.Width, imageSize.Width) + bwidth;
                        sizeNeeded.Height = _ContentSize.Height + imageSize.Height + bheight;
                        break;
                    default:
                        sizeNeeded.Width = _ContentSize.Width + imageSize.Width + bwidth;
                        sizeNeeded.Height = Math.Max(imageSize.Height, _ContentSize.Height) + bheight;
                        break;
                }
                if (panel.GroupColumns.Count > 0)
                {
                    if (panel.Columns.FirstVisibleColumn == GridColumn)
                        sizeNeeded.Width += Dpi.Width(panel.LevelIndentSize.Width * (indentLevel + 1));
                }
                if (GridRow != null &&
                    (GridRow.Rows.Count > 0 || GridRow.RowsUnresolved == true))
                {
                    if (panel.ExpandImage != null)
                    {
                        sizeNeeded.Height = Math.Max(sizeNeeded.Height,
                            Dpi.Height(panel.ExpandImage.Height + 4));
                    }
                    if (panel.CollapseImage != null)
                    {
                        sizeNeeded.Height = Math.Max(sizeNeeded.Height,
                            Dpi.Height(panel.CollapseImage.Height + 4));
                    }
                }
                if (panel.CheckBoxes == true)
                {
                    sizeNeeded.Height = Math.Max(sizeNeeded.Height,
                        Dpi.Height(panel.CheckBoxSize.Height));
                    sizeNeeded.Width += Dpi.Width(CheckBoxSpacing * 2);
                }
            }
            sizeNeeded.Width += Dpi.Width3;
            sizeNeeded.Height += Dpi.Width3;
            if (constraintSize.Width > 0)
                sizeNeeded.Width = constraintSize.Width;
            _MeasuredSize = sizeNeeded;
            Size = sizeNeeded;
        }
        #endregion
        #endregion
        #region ArrangeOverride
        /// 
        /// Performs the arrange pass layout of the item
        /// when final position and size of the item has been set.
        /// 
        /// Layout information.
        /// 
        /// 
        protected override void ArrangeOverride(GridLayoutInfo layoutInfo,
            GridLayoutStateInfo stateInfo, Rectangle layoutBounds)
        {
            GridPanel panel = stateInfo.GridPanel;
            Rectangle r = layoutBounds;
            r.X += _IndentLevel * Dpi.Width(panel.LevelIndentSize.Width);
            r.Width = panel.TreeButtonIndent;
            ArrangeExpandButton(panel, ref r);
            ArrangeCheckBox(panel, r);
            _toolTipText = null;
        }
        #region ArrangeExpandButton
        private void ArrangeExpandButton(GridPanel panel, ref Rectangle r)
        {
            if (IsPrimaryCell == true)
            {
                Rectangle t = Rectangle.Empty;
                if (panel.ShowTreeButtons == true)
                {
                    if (NeedsExpandButton() == true)
                    {
                        t = r;
                        Size size = panel.GetTreeButtonSize();
                        t.X += (r.Width - size.Width) / 2;
                        t.Y += (r.Height - size.Height) / 2 - 1;
                        t.Size = size;
                    }
                    int tbi = panel.TreeButtonIndent;
                    r.X += tbi;
                    r.Width -= tbi;
                }
                else
                {
                    if (panel.CheckBoxes == true)
                    {
                        int cbs = Dpi.Width(CheckBoxSpacing);
                        r.X += cbs;
                        r.Width -= cbs;
                    }
                }
                GridRow.ExpandButtonBounds = t;
            }
        }
        #region NeedsExpandButton
        private bool NeedsExpandButton()
        {
            GridRow row = GridRow;
            if (row != null)
            {
                if (row.ShowTreeButton == true)
                {
                    if (row.RowsUnresolved || row.HasVisibleItems)
                        return (true);
                }
            }
            return (false);
        }
        #endregion
        #endregion
        #region ArrangeCheckBox
        private void ArrangeCheckBox(GridPanel panel, Rectangle r)
        {
            if (IsPrimaryCell == true)
            {
                if (GridRow.HasCheckBox == true)
                {
                    Size cbSize = Dpi.Size(panel.CheckBoxSize);
                    int n = Math.Max(cbSize.Width, cbSize.Height);
                    r.Y += (r.Height - n) / 2;
                    r.Width = n;
                    r.Height = n;
                    GridRow.CheckBoxBounds = r;
                }
                else
                {
                    GridRow.CheckBoxBounds = Rectangle.Empty;
                }
            }
        }
        #endregion
        #endregion
        #region RenderOverride
        /// 
        /// Performs drawing of the item and its children.
        /// 
        /// Holds contextual rendering information.
        protected override void RenderOverride(GridRenderInfo renderInfo)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                Graphics g = renderInfo.Graphics;
                CheckMeasure(panel, g);
                CellRange cr = GetStateCellRange();
                bool rendered = (cr != null && (cr.RenderCount == panel.RenderCount));
                Rectangle backBounds = (cr != null) ? cr.BackBounds : BackBounds;
                Rectangle bounds = GetBounds(panel, backBounds);
                if (backBounds.IntersectsWith(SuperGrid.ViewRectEx) == true)
                {
                    if (rendered == false)
                    {
                        CellHighlightMode mode = GetCellHighlightMode(panel);
                        CellVisualStyle style = GetEffectiveStyle();
                        RenderCellBackground(g, panel, backBounds, mode);
                        RenderGridBorder(g, panel, backBounds);
                        int n = RenderLevelData(g, panel);
                        Rectangle r = bounds;
                        r.X += n;
                        r.Width -= n;
                        RenderCellBorder(g, panel, r, style);
                        RenderImageAndValue(g, panel, bounds, mode, style);
                        if (this.IsDataError == true)
                            RenderDataError(g);
                        else if (GridRow.IsDeleted == true)
                            RenderDeleted(g);
                        RenderFocusRect(g, panel, cr, backBounds);
                        if (cr != null)
                            cr.RenderCount = panel.RenderCount;
                    }
                    else
                    {
                        RenderLevelData(g, panel);
                    }
                }
            }
        }
        #region CheckMeasure
        private void CheckMeasure(GridPanel panel, Graphics g)
        {
            if (NeedsMeasured == true)
            {
                NeedsMeasured = false;
                Size size = new Size(GridColumn.Size.Width, GridRow.Size.Height);
                if (panel.VirtualMode == false)
                    MeasureCell(g, panel, IndentLevel, size);
                size.Height = GridRow.FixedRowHeight;
                Size = size;
                UpdateBoundingRects();
            }
        }
        #endregion
        #region RenderCellBackground
        private void RenderCellBackground(Graphics g,
            GridPanel panel, Rectangle r, CellHighlightMode mode)
        {
            if (SuperGrid.DoPreRenderCellEvent(g, this, RenderParts.Background, r) == false)
            {
                RenderCellBackgroundEx(panel, g, r, mode);
                SuperGrid.DoPostRenderCellEvent(g, this, RenderParts.Background, r);
            }
        }
        #region RenderCellBackgroundEx
        private void RenderCellBackgroundEx(GridPanel panel,
            Graphics g, Rectangle r, CellHighlightMode type)
        {
            if (SuperGrid.EditorCell == this)
            {
                TextBox tb = GetInternalEditControl() as TextBox;
                if (tb != null)
                {
                    using (Brush br = new SolidBrush(tb.BackColor))
                        RenderBackground(g, r, type, br);
                    return;
                }
            }
            using (Brush br = GetContentBrush(panel, r, type))
                RenderBackground(g, r, type, br);
        }
        #region RenderBackground
        private void RenderBackground(
            Graphics g, Rectangle r, CellHighlightMode type, Brush br)
        {
            if (type == CellHighlightMode.Partial ||
                type == CellHighlightMode.Content)
            {
                r = RenderPartialBackground(g, r, type);
            }
            if (r.Width > 0 && r.Height > 0)
                g.FillRectangle(br, r);
        }
        #endregion
        #region RenderPartialBackground
        private Rectangle RenderPartialBackground(
            Graphics g, Rectangle r, CellHighlightMode type)
        {
            CellVisualStyle defaultStyle =
                GetEffectiveStyle(StyleType.Default);
            using (Brush br = defaultStyle.Background.GetBrush(r))
                g.FillRectangle(br, r);
            r = GetAdjustedBounds(ContentBounds);
            if (type == CellHighlightMode.Content)
            {
                IGridCellEditControl editor = GetInternalRenderControl();
                r = GetEditPanelBounds(editor, r);
            }
            r.Inflate(1, 1);
            return (r);
        }
        #endregion
        #region GetContentBrush
        private Brush GetContentBrush(
            GridPanel panel, Rectangle r, CellHighlightMode type)
        {
            if (IsEmptyCell == true && panel.AllowEmptyCellSelection == false)
            {
                CellVisualStyle style =
                    GetEffectiveStyle(StyleType.Empty);
                return (style.Background.GetBrush(r));
            }
            if (IsSelectable == false)
            {
                CellVisualStyle style =
                    GetEffectiveStyle(StyleType.NotSelectable);
                return (style.Background.GetBrush(r));
            }
            if (type == CellHighlightMode.None)
            {
                CellVisualStyle style =
                    GetEffectiveStyle(false);
                return (style.Background.GetBrush(r));
            }
            CellVisualStyle contentStyle = GetContentStyle(panel);
            return (contentStyle.Background.GetBrush(r));
        }
        #endregion
        #region GetContentStyle
        private CellVisualStyle GetContentStyle(GridPanel panel)
        {
            if (panel.SelectionGranularity == SelectionGranularity.Row)
            {
                StyleState cellState = StyleState.Default;
                if (IsReadOnly == true)
                    cellState |= StyleState.ReadOnly;
                Rectangle t = ViewRect;
                Rectangle r = GridRow.Bounds;
                CellRange cr = GetCellRange();
                if (cr != null)
                    r = Rectangle.Union(r, cr.BackBounds);
                r.Intersect(t);
                if (SuperGrid.ScrollBarScrolling == false)
                {
                    if (panel.RowHighlightType == RowHighlightType.Full)
                    {
                        if (GridRow.IsMouseOver == true)
                            cellState |= StyleState.MouseOver;
                    }
                    else
                    {
                        if (r.Contains(SuperGrid.PointToClient(Control.MousePosition)))
                            cellState |= StyleState.MouseOver;
                    }
                }
                if (IsSelected == true)
                    cellState |= StyleState.Selected;
                return (GetEffectiveStyle(cellState));
            }
            return (GetEffectiveStyle());
        }
        #endregion
        #region GetCellHighlightMode
        private CellHighlightMode GetCellHighlightMode(GridPanel panel)
        {
            if (panel.SelectionGranularity != SelectionGranularity.Cell)
            {
                switch (panel.RowHighlightType)
                {
                    case RowHighlightType.None:
                        return (CellHighlightMode.None);
                    case RowHighlightType.PrimaryColumnOnly:
                        return (IsPrimaryCell == true
                            ? CellHighlightMode.Full : CellHighlightMode.None);
                    default:
                        return (CellHighlightMode.Full);
                }
            }
            if (GridRow.IsSelected == true)
                return (CellHighlightMode.Full);
            return (GridColumn.CellHighlightMode);
        }
        #endregion
        #endregion
        #endregion
        #region RenderGridBorder
        private void RenderGridBorder(
            Graphics g, GridPanel panel, Rectangle r)
        {
            if (SuperGrid.DoPreRenderCellEvent(g, this, RenderParts.Border, r) == false)
            {
                RenderGridBorderEx(g, panel, r);
                SuperGrid.DoPostRenderCellEvent(g, this, RenderParts.Border, r);
            }
        }
        private void RenderGridBorderEx(
            Graphics g, GridPanel panel, Rectangle r)
        {
            if (panel.GridLines != GridLines.None)
            {
                GridPanelVisualStyle pstyle = panel.GetEffectiveStyle();
                if (panel.GridLines == GridLines.Both)
                    RenderBothGridBorders(g, pstyle, r);
                else if (panel.GridLines == GridLines.Vertical)
                    RenderVGridBorder(g, pstyle, r);
                else if (panel.GridLines == GridLines.Horizontal)
                    RenderHGridBorder(g, pstyle, r);
            }
        }
        #region RenderBothGridBorders
        private void RenderBothGridBorders(
            Graphics g, GridPanelVisualStyle pstyle, Rectangle r)
        {
            RenderHGridBorder(g, pstyle, r);
            RenderVGridBorder(g, pstyle, r);
        }
        #endregion
        #region RenderHGridBorder
        private void RenderHGridBorder(Graphics g, GridPanelVisualStyle pstyle, Rectangle r)
        {
            if (pstyle.HorizontalLinePattern != LinePattern.None &&
                pstyle.HorizontalLinePattern != LinePattern.NotSet)
            {
                using (Pen pen = new Pen(pstyle.HorizontalLineColor, Dpi.Height1))
                {
                    pen.DashStyle = (DashStyle)pstyle.HorizontalLinePattern;
                    pen.DashOffset = r.X % 2;
                    g.DrawLine(pen, r.X, r.Top - 1, r.Right - 1, r.Top - 1);
                    g.DrawLine(pen, r.X, r.Bottom - 1, r.Right - 1, r.Bottom - 1);
                }
            }
        }
        #endregion
        #region RenderVGridBorder
        private void RenderVGridBorder(Graphics g, GridPanelVisualStyle pstyle, Rectangle r)
        {
            if (pstyle.VerticalLinePattern != LinePattern.None &&
                pstyle.VerticalLinePattern != LinePattern.NotSet)
            {
                using (Pen pen = new Pen(pstyle.VerticalLineColor, Dpi.Width1))
                {
                    pen.DashStyle = (DashStyle)pstyle.VerticalLinePattern;
                    pen.DashOffset = r.Top % 2;
                    g.DrawLine(pen, r.Right - 1, r.Top, r.Right - 1, r.Bottom);
                }
            }
        }
        #endregion
        #endregion
        #region RenderLevelData
        private int RenderLevelData(Graphics g, GridPanel panel)
        {
            int n = 0;
            if (IsPrimaryCell == true)
            {
                Rectangle r = BackBounds;
                int x = r.X;
                RenderCellTreeData(g, panel, ref r);
                RenderCellCheckBox(g, panel, ref r);
                n = r.X - x;
            }
            else
            {
                if (panel.GroupColumns.Count > 0)
                {
                    if (panel.Columns.FirstVisibleColumn == GridColumn)
                        n = Dpi.Width(panel.LevelIndentSize.Width * _IndentLevel);
                }
            }
            return (n);
        }
        #region RenderCellTreeData
        private void RenderCellTreeData(
            Graphics g, GridPanel panel, ref Rectangle r)
        {
            int liw = Dpi.Width(panel.LevelIndentSize.Width);
            if (panel.ShowTreeButtons == true || panel.ShowTreeLines == true)
            {
                GridRow row = GridRow;
                Rectangle t = row.ExpandButtonBounds;
                if (row.IsVFrozen == false)
                    t.Y -= VScrollOffset;
                if (panel.IsSubPanel == true || GridColumn.IsHFrozen == false)
                    t.X -= HScrollOffset;
                bool hasExpandButton = (panel.ShowTreeButtons == true &&
                    row.ExpandButtonBounds.IsEmpty == false);
                int tbi = panel.TreeButtonIndent;
                if (panel.ShowTreeLines == true)
                {
                    Rectangle p = r;
                    p.Y--;
                    p.Height++;
                    TreeDisplay.RenderLines(g, 
                        panel, p, row, _IndentLevel, liw, tbi, hasExpandButton);
                }
                if (hasExpandButton == true)
                {
                    Point pt = Control.MousePosition;
                    pt = SuperGrid.PointToClient(pt);
                    bool hot = t.Contains(pt);
                    Image image = (row.Expanded == true)
                        ? panel.GetCollapseButton(g, hot) : panel.GetExpandButton(g, hot);
                    ExpandDisplay.RenderButton(g, image, t, r);
                }
                r.X += tbi;
                r.Width -= tbi;
            }
            int n = liw * _IndentLevel;
            r.X += n;
            r.Width -= n;
        }
        #endregion
        #region RenderCellCheckBox
        private void RenderCellCheckBox(
            Graphics g, GridPanel panel, ref Rectangle r)
        {
            if (GridRow.HasCheckBox == true)
            {
                Rectangle t = CheckBoxBounds;
                if (GridRow.IsVFrozen == false)
                    t.Y -= VScrollOffset;
                if (panel.IsSubPanel == true || GridColumn.IsHFrozen == false)
                    t.X -= HScrollOffset;
                Region clip = null;
                if (t.Right >= r.Right || t.Height >= r.Height)
                {
                    Rectangle z = r;
                    z.Width--;
                    z.Height--;
                    clip = g.Clip;
                    g.SetClip(z, CombineMode.Intersect);
                }
                if (GridRow.Checked == true)
                {
                    CheckDisplay.RenderCheckbox(g, t,
                        CheckBoxState.CheckedNormal, ButtonState.Checked);
                }
                else
                {
                    CheckDisplay.RenderCheckbox(g, t,
                        CheckBoxState.UncheckedNormal, ButtonState.Normal);
                }
                if (clip != null)
                    g.Clip = clip;
                r.X += panel.CheckBoxSize.Width + (CheckBoxSpacing * 2);
                r.Width -= (panel.CheckBoxSize.Width + (CheckBoxSpacing * 2));
            }
        }
        #endregion
        #endregion
        #region RenderCellBorder
        private void RenderCellBorder(Graphics g,
            GridPanel panel, Rectangle r, CellVisualStyle style)
        {
            if (SuperGrid.DoPreRenderCellEvent(g, this, RenderParts.Border, r) == false)
            {
                RenderCellBorderEx(g, panel, r, style);
                SuperGrid.DoPostRenderCellEvent(g, this, RenderParts.Border, r);
            }
        }
        #region RenderCellBorderEx
        private void RenderCellBorderEx(
            Graphics g, GridPanel panel, Rectangle r, CellVisualStyle style)
        {
            Rectangle t = GetBorderRect(panel, r, style);
            style.RenderBorder(g, t);
        }
        #region GetBorderRect
        private Rectangle GetBorderRect(
            GridPanel panel, Rectangle r, CellVisualStyle style)
        {
            r.X += Dpi.Width(style.Margin.Left);
            r.Width -= Dpi.Width(style.Margin.Horizontal);
            r.Y += Dpi.Height(style.Margin.Top);
            r.Height -= Dpi.Height(style.Margin.Vertical);
            if (panel.GridLines == GridLines.Horizontal || panel.GridLines == GridLines.Both)
                r.Height -= Dpi.Height1;
            if (panel.GridLines == GridLines.Vertical || panel.GridLines == GridLines.Both)
                r.Width -= Dpi.Width1;
            return (r);
        }
        #endregion
        #endregion
        #endregion
        #region RenderImageAndValue
        private void RenderImageAndValue(Graphics g,
            GridPanel panel, Rectangle bounds, CellHighlightMode mode, CellVisualStyle style)
        {
            Rectangle r = GetAdjustedBounds(GetContentBounds(panel, bounds));
            if (style.ImageOverlay != ImageOverlay.Top)
                RenderCellImage(g, panel, style, bounds, r, mode);
            if (CanRenderCellValue() == true)
            {
                if (SuperGrid.DoPreRenderCellEvent(g, this, RenderParts.Content, r) == false)
                {
                    RenderCellValue(g, style, r);
                    SuperGrid.DoPostRenderCellEvent(g, this, RenderParts.Content, r);
                }
            }
            else
            {
                if (SuperGrid.EditorCell == this && Visible == true && IsEmptyCell == false)
                    RenderCellInfo(g, panel);
            }
            if (style.ImageOverlay == ImageOverlay.Top)
                RenderCellImage(g, panel, style, bounds, r, mode);
        }
        #region RenderCellImage
        private void RenderCellImage(Graphics g, GridPanel panel,
            CellVisualStyle style, Rectangle bounds, Rectangle r, CellHighlightMode type)
        {
            object figure = style.GetFigure(panel);
            if (figure != null)
            {
                r = style.GetFigureBounds(panel, r);
                r.Intersect(bounds);
                if (r.Width > 0 && r.Height > 0)
                {
                    if (figure is Image)
                    {
                        if (CanHighlightCell(style, type) == true)
                            DrawHighlightImage(g, (Image)figure, style, r);
                        else
                            g.DrawImageUnscaledAndClipped((Image)figure, r);
                    }
                    else
                    {
                        SymbolDef sd = (SymbolDef)figure;
                        using (Brush br = new SolidBrush(sd.SymbolColor))
                            g.DrawString(sd.SymbolRealized, sd.SymbolFont, br, r);
                    }
                }
            }
        }
        #region CanHighlightCell
        private bool CanHighlightCell(
            CellVisualStyle style, CellHighlightMode type)
        {
            switch (style.ImageHighlightMode)
            {
                case ImageHighlightMode.Always:
                    return (true);
                case ImageHighlightMode.Never:
                    return (false);
                default:
                    if (IsSelected == false)
                        return (false);
                    return (type == CellHighlightMode.Content ||
                            type == CellHighlightMode.Partial);
            }
        }
        #endregion
        #region DrawHighlightImage
        private void DrawHighlightImage(Graphics g,
            Image image, CellVisualStyle style, Rectangle r)
        {
            Color color = GetSimpleColor(style);
            float[][] ptsArray =
            {
                new float[] {(float)color.R / 255, 0, 0, 0, 0},
                new float[] {0, (float)color.G / 255, 0, 0, 0},
                new float[] {0, 0, (float)color.B / 255, 0, 0},
                new float[] {0f, 0, 0, 1, 0},
                new float[] {.15f, .15f, .15f, 0, 1}
            };
            ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
            ImageAttributes imgAttribs = new ImageAttributes();
            imgAttribs.SetColorMatrix(clrMatrix,
                ColorMatrixFlag.Default, ColorAdjustType.Default);
            g.DrawImage(image, r,
                0, 0, style.Image.Width, image.Height,
                GraphicsUnit.Pixel, imgAttribs);
        }
        #endregion
        #region GetSimpleColor
        private Color GetSimpleColor(CellVisualStyle style)
        {
            Color color1;
            Color color2;
            if (style.Background.BackColorBlend.Colors != null &&
                style.Background.BackColorBlend.Colors.Length > 0)
            {
                Color[] colors = style.Background.BackColorBlend.Colors;
                color1 = colors[0];
                color2 = colors[colors.Length - 1];
            }
            else
            {
                color1 = style.Background.Color1;
                color2 = style.Background.Color2;
            }
            if (color2.IsEmpty == true)
                return (color1);
            switch (style.Alignment)
            {
                case Alignment.TopLeft:
                case Alignment.TopCenter:
                case Alignment.TopRight:
                    return (color1);
                case Alignment.MiddleLeft:
                case Alignment.MiddleCenter:
                case Alignment.MiddleRight:
                    return (Color.FromArgb((color1.R + color2.R) / 2, (color1.G + color2.G) / 2, (color1.B + color2.B) / 2));
                default:
                    return (color2);
            }
        }
        #endregion
        #endregion
        #region CanRenderCellValue
        private bool CanRenderCellValue()
        {
            if (Visible == false || IsEmptyCell == true || SuperGrid.EditorCell == this)
                return (false);
            if (SuperGrid.NonModalEditorCell == this)
                return (false);
            return (true);
        }
        #endregion
        #region RenderCellValue
        //private int _RenderCount;
        private void RenderCellValue(
            Graphics g, CellVisualStyle style, Rectangle r)
        {
            if (r.Width > 0)
            {
                GridColumn column = GridColumn;
                if (column != null)
                {
                    IGridCellEditControl renderer;
                    if (SuperGrid.ActiveEditor != null ||
                        (MouseRenderer == null || MouseRenderer.EditorCell != this))
                    {
                        renderer = GetInternalRenderControl();
                    }
                    else
                    {
                        renderer = MouseRenderer;
                    }
                    if (renderer != null && ((Control)renderer).IsDisposed == false)
                    {
                        CellRender(g, style, renderer);
                        //using (StringFormat sf = new StringFormat())
                        //{
                        //    sf.Alignment = StringAlignment.Far;
                        //    sf.LineAlignment = StringAlignment.Far;
                        //    sf.Trimming = StringTrimming.EllipsisCharacter;
                        //    g.DrawString((++_RenderCount).ToString(),
                        //                 SystemFonts.DefaultFont, Brushes.Red, r, sf);
                        //    //sf.LineAlignment = StringAlignment.Near;
                        //    //g.DrawString((_MeasureCount).ToString(),
                        //    //             SystemFonts.DefaultFont, Brushes.Blue, r, sf);
                        //}
                    }
                }
            }
        }
        #endregion
        #endregion
        #region RenderDataError
        private void RenderDataError(Graphics g)
        {
            Rectangle r = Bounds;
            int w = Dpi.Width5;
            int h = Dpi.Width5;
            if (r.Width > w && r.Height > h)
                r.Inflate(-w, -h);
            using (SolidBrush br = new SolidBrush(Color.FromArgb(64, Color.Crimson)))
                g.FillRectangle(br, r);
        }
        #endregion
        #region RenderDeleted
        private void RenderDeleted(Graphics g)
        {
            using (SolidBrush br = new SolidBrush(Color.FromArgb(128, Color.LightGray)))
                g.FillRectangle(br, Bounds);
        }
        #endregion
        #region RenderFocusRect
        private void RenderFocusRect(Graphics g,
            GridPanel panel, CellRange cr, Rectangle backBounds)
        {
            if (panel.FocusCuesEnabled == true)
            {
                if (IsFocused() == true)
                {
                    if (panel.EnableCellMerging == true && IsFocusedRow(cr) == true)
                        RenderRowFocusRect(g, panel, backBounds, cr);
                    else if (IsFocusedCell(cr) == true)
                    {
                        Rectangle r;
                        if (cr != null)
                        {
                            r = backBounds;
                            if (r.X <= 0)
                            {
                                r.X++;
                                r.Width--;
                            }
                            r.Width -= Dpi.Width1;
                            r.Height -= Dpi.Height1;
                        }
                        else
                        {
                            r = HighLightBounds;
                        }
                        RenderCellFocusRect(g, r);
                    }
                }
            }
        }
        #region IsFocused
        private bool IsFocused()
        {
            if (IsDesignerHosted == true)
                return (false);
            return (SuperGrid.ContainsFocus == true);
        }
        #endregion
        #region IsFocusedRow
        private bool IsFocusedRow(CellRange cr)
        {
            if (SuperGrid.ActiveElement is GridRow)
            {
                GridRow arow = SuperGrid.ActiveElement as GridRow;
                if (cr == null)
                    return (arow == GridRow);
                if (arow.Parent == GridRow.Parent)
                    return (arow.RowIndex >= cr.RowStart && arow.RowIndex < cr.RowEnd);
            }
            return (false);
        }
        #endregion
        #region IsFocusedCell
        private bool IsFocusedCell(CellRange cr)
        {
            GridCell acell = SuperGrid.ActiveElement as GridCell;
            if (acell == null)
                return (false);
            if (cr != null)
                return (cr == acell.GetCellRange());
            return (IsSameCell(acell));
        }
        #region IsSameCell
        internal bool IsSameCell(GridCell cell)
        {
            if (cell != null)
            {
                return (ColumnIndex == cell.ColumnIndex &&
                    GridRow == cell.GridRow);
            }
            return (false);
        }
        #endregion
        #endregion
        #region RenderRowFocusRect
        private void RenderRowFocusRect(
            Graphics g, GridPanel panel, Rectangle r, CellRange cr)
        {
            if (IsEmptyCell == false)
            {
                SmoothingMode sm = g.SmoothingMode;
                g.SmoothingMode = SmoothingMode.None;
                Rectangle t = (IsVFrozen == true ? r : SViewRect);
                Rectangle lc = GetLeftCell(panel, t, cr);
                Rectangle rc = GetRightCell(panel, t, cr);
                if (lc.IsEmpty == true && rc.IsEmpty == true)
                {
                    RenderCellFocusRect(g, r);
                }
                else
                {
                    using (Pen pen = new Pen(Color.Black, 1))
                    {
                        pen.DashStyle = DashStyle.Dot;
                        r.Width -= Dpi.Width1 + 1;
                        r.Height -= Dpi.Height1 + 1;
                        r.Intersect(t);
                        RenderVertFocus(g, r, lc, rc, pen);
                        RenderHorzFocus(g, r, lc, rc, pen);
                    }
                }
                g.SmoothingMode = sm;
            }
        }
        #region RenderVertFocus
        private void RenderVertFocus(Graphics g,
            Rectangle r, Rectangle lc, Rectangle rc, Pen pen)
        {
            pen.DashOffset = (r.X % 2);
            if (lc.IsEmpty == false)
            {
                if (r.Width > 1)
                {
                    if (r.Y < lc.Y - pen.DashOffset)
                        g.DrawLine(pen, r.X, r.Y, r.X, lc.Y);
                    if (lc.Bottom < r.Bottom - pen.DashOffset)
                        g.DrawLine(pen, r.X, lc.Bottom, r.X, r.Bottom);
                }
            }
            else
            {
                if (r.Height > 1)
                    g.DrawLine(pen, r.X, r.Y, r.X, r.Bottom);
            }
            if (rc.IsEmpty == false)
            {
                if (r.Width > 1)
                {
                    if (r.Y < rc.Y - pen.DashOffset)
                        g.DrawLine(pen, r.Right, rc.Y, r.Right, r.Y);
                    if (rc.Bottom < r.Bottom - pen.DashOffset)
                        g.DrawLine(pen, r.Right, rc.Bottom, r.Right, r.Bottom);
                }
            }
            else
            {
                if (r.Height > 1)
                    g.DrawLine(pen, r.Right, r.Y, r.Right, r.Bottom);
            }
        }
        #endregion
        #region RenderHorzFocus
        private void RenderHorzFocus(Graphics g,
            Rectangle r, Rectangle lc, Rectangle rc, Pen pen)
        {
            if (r.Width > 1)
            {
                int x1 = 0;
                int x2 = 0;
                if (lc.IsEmpty == false)
                {
                    if (lc.Y <= r.Y)
                        x1 = r.X - lc.Right;
                }
                if (rc.IsEmpty == false)
                {
                    if (rc.Y <= r.Y)
                    {
                        if (rc.X > r.Right)
                            x2 = rc.X - r.Right + 1;
                    }
                }
                pen.DashOffset = ((r.X - x1) % 2);
                if (r.Right + x2 - (r.X - x1) >  pen.DashOffset)
                    g.DrawLine(pen, r.X - x1, r.Y, r.Right + x2, r.Y);
                x1 = 0;
                x2 = 0;
                if (lc.IsEmpty == false)
                {
                    if (lc.Bottom >= r.Bottom)
                    {
                        x1 = r.X - lc.Right;
                        x2 = x1 - 1;
                    }
                }
                if (rc.IsEmpty == false)
                {
                    if (rc.Bottom >= r.Bottom)
                    {
                        if (rc.X > r.Right)
                            x2 = rc.X - r.Right + 1;
                    }
                }
                pen.DashOffset = ((r.X - x1) % 2);
                if (r.Right + x2 - (r.X - x1) > pen.DashOffset)
                    g.DrawLine(pen, r.X - x1, r.Bottom, r.Right + x2, r.Bottom);
            }
        }
        #endregion
        #region GetLeftCell
        private Rectangle GetLeftCell(GridPanel panel, Rectangle t, CellRange cr)
        {
            GridColumnCollection columns = panel.Columns;
            GridColumn col = (cr != null)
                ? columns.GetPrevVisibleColumn(columns.ColumnAtDisplayIndex(cr.ColumnStart))
                : columns.GetPrevVisibleColumn(GridColumn);
            Rectangle r = GetCellRect(col);
            r.Width -= Dpi.Width1 + 1;
            r.Height -= Dpi.Height1 + 1;
            t.Intersect(r);
            return (t);
        }
        #endregion
        #region GetRightCell
        private Rectangle GetRightCell(GridPanel panel, Rectangle t, CellRange cr)
        {
            GridColumnCollection columns = panel.Columns;
            GridColumn col = (cr != null)
                ? columns.GetNextVisibleColumn(columns.ColumnAtDisplayIndex(cr.ColumnEnd - 1))
                : columns.GetNextVisibleColumn(GridColumn);
            while (col != null)
            {
                if (col.IsOnScreen == true)
                    break;
                col = columns.GetNextVisibleColumn(col);
            }
            Rectangle r = GetCellRect(col);
            r.Width -= Dpi.Width1 + 1;
            r.Height -= Dpi.Height1 + 1;
            t.Intersect(r);
            return (t);
        }
        #endregion
        #region GetCellRect
        private Rectangle GetCellRect(GridColumn col)
        {
            if (col != null)
            {
                GridRow arow = SuperGrid.ActiveElement as GridRow;
                if (arow != null)
                {
                    GridCell cell = arow.GetCell(col.ColumnIndex);
                    if (cell != null)
                    {
                        CellRange cr2 = cell.GetStateCellRange();
                        if (cr2 != null)
                            return (cr2.BackBounds);
                        return (cell.Bounds);
                    }
                }
            }
            return (Rectangle.Empty);
        }
        #endregion
        #endregion
        #region RenderCellFocusRect
        private void RenderCellFocusRect(Graphics g, Rectangle bounds)
        {
            SmoothingMode sm = g.SmoothingMode;
            g.SmoothingMode = SmoothingMode.None;
            ControlPaint.DrawFocusRectangle(g, bounds);
            g.SmoothingMode = sm;
        }
        #endregion
        #endregion
        #endregion
        #region GetCellRange
        ///
        ///Gets the CellRange, if any, that the cell is a member of.
        ///
        ///CellRange or null.
        public CellRange GetCellRange()
        {
            GridContainer cont = RowContainer;
            if (cont != null)
                return (cont.GetCellRange(this));
            return (null);
        }
        internal CellRange GetStateCellRange()
        {
            CellRange cr = GetCellRange();
            if (cr != null)
            {
                if (cr.Suspended == true)
                    cr = null;
            }
            Merged = (cr != null);
            return (cr);
        }
        #endregion
        #region SuspendMerge
        ///
        ///If the cell is currently participating in a merged range of
        ///cells, then the merge will be suspended until the user clicks
        ///away from the merged range (or ResumeMerge is called for the cell).
        ///
        ///If true, cell will be made the active cell.
        public bool SuspendMerge(bool activate)
        {
            CellRange cr = GetStateCellRange();
            if (cr != null)
                SuspendMerge(cr);
            if (cr == null || cr.Suspended == true)
            {
                if (activate == true)
                {
                    if (CanSetActiveCell(GridPanel) == true)
                    {
                        _needsMouseEnter = true;
                        SetActive(true);
                    }
                }
                return (true);
            }
            return (false);
        }
        internal void SuspendMerge(CellRange cr)
        {
            GridContainer cont = RowContainer;
            if (cont != null)
                cont.SuspendMerge(cr);
        }
        #endregion
        #region ResumeMerge
        ///
        ///Resumes the suspended merge where the cell is a participant
        ///
        public void ResumeMerge(GridCell aCell)
        {
            GridContainer cont = RowContainer;
            if (cont != null)
            {
                if (ShouldResumeMerge(cont, aCell) == true)
                    RowContainer.ResumeMerge();
            }
        }
        private bool ShouldResumeMerge(GridContainer cont, GridCell aCell)
        {
            if (aCell == null)
                return (true);
            GridContainer aCont = aCell.RowContainer;
            if (aCont != cont)
                return (true);
            
            CellRange cr = cont.SuspendedRange;
            if (cr != null)
            {
                if (cr.Equals(aCont.GetCellRange(aCell)) == true)
                    return (false);
            }
            return (true);
        }
        #endregion
        #region GetProposedSize
        private Size GetProposedSize(Graphics g, CellVisualStyle style, Size constraintSize)
        {
            return (GetProposedSize(g, style, constraintSize, null, CellSizingSource.ActualAndFormattedValues));
        }
        private Size GetProposedSize(Graphics g,
            CellVisualStyle style, Size constraintSize, IGridCellEditControl editor, CellSizingSource sizingSource)
        {
            Size size = Size.Empty;
            if (IsValueExpression == true && ExpValue != null)
            {
                size = GetModalSize(g, ExpValue.ToString(), style, constraintSize);
            }
            else
            {
                if (editor == null)
                {
                    if (CellEditMode != CellEditMode.Modal)
                    {
                        if (MouseRenderer == null || MouseRenderer.EditorCell == this)
                            editor = GetInternalEditControl();
                        if (editor != null && editor.EditorCell != this)
                        {
                            if (SuperGrid.ActiveNonModalEditor == editor)
                                editor = null;
                        }
                        if (editor == null)
                            editor = GetInternalRenderControl();
                    }
                    else
                    {
                        editor = SuperGrid.EditorCell == this
                            ? GetInternalEditControl() : GetInternalRenderControl();
                    }
                }
                if (editor != null)
                {
                    bool suspended = editor.SuspendUpdate;
                    try
                    {
                        editor.SuspendUpdate = true;
                        if (SuperGrid.EditorCell != this)
                            InitializeContext(DataContext.CellProposedSize, editor, style);
                        if (editor.CellEditMode == CellEditMode.Modal)
                        {
                            Size sizeActual = Size.Empty;
                            Size sizeFormatted = Size.Empty;
                            string s = editor.EditorFormattedValue;
                            SuperGrid.DoGetCellFormattedValueEvent(this, ref s, ref sizingSource);
                            if ((sizingSource & CellSizingSource.ActualValue) == CellSizingSource.ActualValue)
                                sizeActual = editor.GetProposedSize(g, this, style, constraintSize);
                            if ((sizingSource & CellSizingSource.FormattedValue) == CellSizingSource.FormattedValue)
                                sizeFormatted = GetModalSize(g, s, style, constraintSize);
                            size.Height = Math.Max(sizeActual.Height, sizeFormatted.Height);
                            size.Width = Math.Max(sizeActual.Width, sizeFormatted.Width);
                        }
                        else
                        {
                            size = editor.GetProposedSize(g, this, style, constraintSize);
                        }
                    }
                    finally
                    {
                        editor.SuspendUpdate = suspended;
                    }
                }
            }
            return (size);
        }
        #region GetModalSize
        private Size GetModalSize(Graphics g,
            string text, CellVisualStyle style, Size constraintSize)
        {
            eTextFormat tf = style.GetTextFormatFlags();
            string s = String.IsNullOrEmpty(text) ? " " : text;
            Size size = (constraintSize.IsEmpty == true)
                            ? TextHelper.MeasureText(g, s, style.Font)
                            : TextHelper.MeasureText(g, s, style.Font, constraintSize, tf);
            return (size);
        }
        #endregion
        #endregion
        #region Mouse support
        #region InternalMouseEnter
        internal override void InternalMouseEnter(EventArgs e)
        {
            base.InternalMouseEnter(e);
            if (GridColumn != null)
            {
                GridColumn.IsMouseOver = true;
                DoRendererMouseEnter();
                SuperGrid.ToolTipText = "";
                _toolTipText = null;
                if (GridPanel.SelectionGranularity != SelectionGranularity.Cell)
                    GridRow.InvalidateRender(GridRow.Bounds);
                SuperGrid.DoCellMouseEnterEvent(this);
            }
        }
        #region DoRendererMouseEnter
        private void DoRendererMouseEnter()
        {
            if (CellEditMode != DotNetBar.SuperGrid.CellEditMode.Modal)
            {
                CellRange cr = GetStateCellRange();
                if (cr != null && cr.Suspended == false)
                    return;
            }
            _needsMouseEnter = true;
            if (SuperGrid.ActiveEditor == null)
            {
                _needsMouseEnter = false;
                if (IsEmptyCell == false)
                {
                    CellVisualStyle style = GetEffectiveStyle();
                    MouseRenderer = null;
                    if (CellEditMode != CellEditMode.Modal)
                        MouseRenderer = GetInternalEditControl();
                    if (MouseRenderer == null)
                        MouseRenderer = GetInternalRenderControl();
                    if (MouseRenderer != null)
                    {
                        switch (CellEditMode)
                        {
                            case CellEditMode.InPlace:
                                InitializeContext(DataContext.CellMouseEvent, MouseRenderer, style);
                                GetCurrentContentSize(style, MouseRenderer);
                                break;
                            case CellEditMode.NonModal:
                                if (CanModifyMerge == true)
                                {
                                    if (SuperGrid.ActiveNonModalEditor == null ||
                                        SuperGrid.ActiveNonModalEditor.CanInterrupt == true)
                                    {
                                        if (SuperGrid.ActiveNonModalEditor != null)
                                        {
                                            SuperGrid.DeactivateNonModalEditor();
                                            if (MouseRenderer == null)
                                                _needsMouseEnter = true;
                                        }
                                        if (MouseRenderer != null)
                                        {
                                            InitializeContext(DataContext.CellMouseEvent, MouseRenderer, style);
                                            PositionEditControl(MouseRenderer);
                                            MouseRenderer.BeginEdit(false);
                                            MouseRenderer.OnCellMouseEnter(EventArgs.Empty);
                                            SuperGrid.ActivateNonModalEditor(MouseRenderer, this);
                                        }
                                    }
                                    else
                                    {
                                        MouseRenderer = null;
                                        _needsMouseEnter = true;
                                    }
                                }
                                break;
                        }
                        if (MouseRenderer != null)
                            InvalidateRender();
                    }
                }
                else
                {
                    InvalidateRender();
                }
            }
        }
        #endregion
        #endregion
        #region InternalMouseLeave
        internal override void InternalMouseLeave(EventArgs e)
        {
            if (GridColumn != null)
            {
                DoRendererMouseLeave(e);
                GridColumn.IsMouseOver = false;
                if (_lastHitArea == CellArea.InCellInfo)
                    ProcessCellInfoLeave();
                if (GridPanel != null)
                {
                    if (GridPanel.SelectionGranularity != SelectionGranularity.Cell)
                        GridRow.InvalidateRender(GridRow.Bounds);
                    else
                        InvalidateRender();
                }
                SuperGrid.DoCellMouseLeaveEvent(this);
                SuperGrid.ToolTipText = "";
                _toolTipText = null;
                _lastHitArea = CellArea.NoWhere;
            }
                
            base.InternalMouseLeave(e);
        }
        #region DoRendererMouseLeave
        internal void DoRendererMouseLeave(EventArgs e)
        {
            if (MouseRenderer != null &&
                ((Control) MouseRenderer).IsDisposed == false)
            {
                if (CellEditMode != CellEditMode.InPlace || _mouseInItem == true)
                    MouseRenderer.OnCellMouseLeave(e);
            }
                
            _mouseInItem = false;
            MouseRenderer = null;
            _needsMouseEnter = false;
            InvalidateRender();
        }
        #endregion
        #endregion
        #region InternalMouseMove
        internal override void InternalMouseMove(MouseEventArgs e)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                if (CapturedItem != null && e.Button != MouseButtons.None)
                    ProcessMouseDownMove(e, panel);
                ProcessMouseMove(e);
                base.InternalMouseMove(e);
                DoRendererMouseMove(e);
                SuperGrid.DoCellMouseMoveEvent(this, e);
            }
        }
        #region DoRendererMouseMove
        private void DoRendererMouseMove(MouseEventArgs e)
        {
            if (_needsMouseEnter == true)
                DoRendererMouseEnter();
            if (MouseRenderer != null &&
                ((Control)MouseRenderer).IsDisposed == false)
            {
                if (CellEditMode == CellEditMode.InPlace)
                {
                    DoInPlaceMouseMove(e);
                }
                else
                {
                    if (CanModify == true)
                    {
                        Rectangle r = GetAdjustedBounds(EditBounds);
                        Point pt = SuperGrid.PointToClient(Control.MousePosition);
                        if (r.Contains(pt) == true)
                            MouseRenderer.OnCellMouseMove(GetControlMouseArgs(e));
                    }
                }
            }
        }
        #region DoInPlaceMouseMove
        private void DoInPlaceMouseMove(MouseEventArgs e)
        {
            if (IsMouseDown == false || _mouseDownInItem == true)
            {
                if (MouseRenderer != null)
                {
                    if (MouseRenderer.EditorCell != this)
                        InitializeContext(DataContext.CellMouseEvent, MouseRenderer, null);
                    Rectangle r = GetAdjustedBounds(ContentBounds);
                    r = GetEditPanelBounds(MouseRenderer, r);
                    bool inItem = r.Contains(e.Location);
                    if (_mouseInItem != inItem)
                    {
                        if (inItem == true)
                            MouseRenderer.OnCellMouseEnter(EventArgs.Empty);
                        else
                            MouseRenderer.OnCellMouseLeave(EventArgs.Empty);
                        _mouseInItem = inItem;
                    }
                    if (_mouseInItem == true)
                        MouseRenderer.OnCellMouseMove(GetControlMouseArgs(e, r));
                }
            }
        }
        #endregion
        #endregion
        #region ProcessMouseDownMove
        private void ProcessMouseDownMove(MouseEventArgs e, GridPanel panel)
        {
            if (_mouseDownHitCell != null)
            {
                if (_mouseDownHitArea == CellArea.InContent)
                {
                    Rectangle r = ViewRect;
                    if (MouseDownPoint.Y < r.Y)
                    {
                        int n = SuperGrid.PrimaryGrid.FixedRowHeight -
                                SuperGrid.PrimaryGrid.FixedHeaderHeight;
                        r.Y -= n;
                        r.Height += n;
                    }
                    if ((e.Y >= r.Y && e.Y < r.Bottom) && (e.X >= r.X && e.X < r.Right))
                    {
                        SuperGrid.DisableAutoScrolling();
                        ProcessInContent(panel, e);
                    }
                    else
                    {
                        SuperGrid.EnableAutoScrolling(
                            AutoScrollEnable.Horizontal | AutoScrollEnable.Vertical, r);
                    }
                }
            }
        }
        #region ProcessInContent
        private void ProcessInContent(GridPanel panel, MouseEventArgs e)
        {
            Point pt = e.Location;
            Rectangle t = SViewRect;
            pt.X = Math.Min(t.Right - 1, pt.X);
            pt.X = Math.Max(t.X, pt.X);
            Rectangle v = panel.BoundsRelative;
            v.Location = panel.PointToScroll(v.Location);
            pt.X = Math.Min(v.Right - 1, pt.X);
            pt.X = Math.Max(v.X, pt.X);
            GridCell lastCell = _hitCell;
            _hitCell = GetCellAt(panel, pt);
            if (DragStarted(panel, pt, e) == false)
            {
                if (_hitCell != null && _hitArea == CellArea.InContent)
                {
                    if (panel.MultiSelect == true)
                    {
                        if (lastCell != null)
                            lastCell.IsMouseOver = false;
                        _hitCell.IsMouseOver = true;
                        if (panel.CellDragBehavior == CellDragBehavior.ExtendSelection)
                        {
                            if (panel.LastProcessedItem is GridCell &&
                                _hitCell != panel.LastProcessedItem)
                            {
                                if (SuperGrid.ActiveEditor == null)
                                    ProcessExtendSelection(panel, true);
                            }
                        }
                    }
                }
            }
        }
        #region DragStarted
        private bool DragStarted(GridPanel panel, Point pt, MouseEventArgs e)
        {
            if (IsDragSelection == true)
            {
                if (IsDragStarted == false)
                {
                    if (DragDrop.DragStarted(_mouseDownPoint, pt) == true)
                    {
                        IsDragStarted = true;
                        if (SuperGrid.DoItemDragEvent(this, e) == true)
                        {
                            IsDragSelection = false;
                            ExtendSelection(panel);
                        }
                    }
                }
                return (true);
            }
            return (false);
        }
        #endregion
        #region GetCellAt
        private GridCell GetCellAt(GridPanel panel, Point pt)
        {
            Rectangle t = ViewRect;
            pt.X = Math.Min(t.Right - 1, pt.X);
            pt.X = Math.Max(t.X, pt.X);
            Rectangle v = panel.BoundsRelative;
            v.Location = panel.PointToScroll(v.Location);
            pt.X = Math.Min(v.Right - 1, pt.X);
            pt.X = Math.Max(v.X, pt.X);
            GridRow row = panel.InternalGetElementAt(pt.X, pt.Y) as GridRow;
            while (row != null)
            {
                GridElement item = row.InternalGetElementAt(pt.X, pt.Y);
                if (item is GridCell)
                    return (item as GridCell);
                row = item as GridRow;
            }
            return (null);
        }
        #endregion
        #endregion
        #endregion
        #region ProcessMouseMove
        private void ProcessMouseMove(MouseEventArgs e)
        {
            _hitArea = GetCellAreaAt(e);
            _hitCell = this;
            if (_hitArea == CellArea.InContent)
                SuperGrid.GridCursor = Cursors.Default;
            if (_hitArea != _lastHitArea)
            {
                ProcessToolTipText(e);
                _lastHitArea = _hitArea;
                InvalidateRender();
            }
            base.InternalMouseMove(e);
        }
        #region ProcessToolTipText
        private void ProcessToolTipText(MouseEventArgs e)
        {
            if (_hitArea == CellArea.InContent)
                ProcessCellToolTip();
            
            else if (_hitArea == CellArea.InCellInfo)
                ProcessCellInfoEnter(e);
            if (_lastHitArea == CellArea.InCellInfo)
                ProcessCellInfoLeave();
        }
        #region ProcessCellToolTip
        private void ProcessCellToolTip()
        {
            SetToolTip(GridPanel.ShowToolTips ? GetToolTipText() : string.Empty);
        }
        #region GetToolTipText
        private string GetToolTipText()
        {
            if (_toolTipText == null)
            {
                CellRange cr = GetStateCellRange();
                if (cr != null)
                {
                    _toolTipText = cr.ToolTip ?? "";
                }
                else
                {
                    string s = "";
                    if (SuperGrid.DoGetCellToolTipEvent(GridPanel, this, ref s) == false)
                    {
                        _toolTipText = "";
                        if (IsEmptyCell == false)
                        {
                            CellVisualStyle style = GetEffectiveStyle();
                            Rectangle r = GetAdjustedBounds(ContentBounds);
                            if (MouseRenderer != null &&
                                ((Control)MouseRenderer).IsDisposed == false)
                            {
                                Size size = new
                                    Size(style.AllowWrap == Tbool.True ? r.Width : 0, 0);
                                using (Graphics g = SuperGrid.CreateGraphics())
                                    size = GetProposedSize(g, style, size, MouseRenderer, CellSizingSource.FormattedValue);
                                if (size.Width > r.Width || size.Height > r.Height)
                                    _toolTipText = String.IsNullOrEmpty(s) ? GetFormattedValue(MouseRenderer) : s;
                            }
                        }
                    }
                    else
                    {
                        _toolTipText = s;
                    }
                }
            }
            return (_toolTipText);
        }
        #endregion
        #endregion
        #region ProcessCellInfoEnter
        private void ProcessCellInfoEnter(MouseEventArgs e)
        {
            SetToolTip(SuperGrid.DoCellInfoEnterEvent(this,
                SuperGrid, SuperGrid.ToolTip, e.Location) ? "" : InfoText);
        }
        #endregion
        #region ProcessCellInfoLeave
        private void ProcessCellInfoLeave()
        {
            SuperGrid.DoCellInfoLeaveEvent(this, SuperGrid, SuperGrid.ToolTip);
        }
        #endregion
        #region SetToolTip
        private void SetToolTip(string toolTipText)
        {
            if (SuperGrid.ToolTipText != _toolTipText)
                SuperGrid.ToolTip.Hide(SuperGrid);
            SuperGrid.ToolTipText = toolTipText;
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #region InternalMouseDown
        internal override void InternalMouseDown(MouseEventArgs e)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                SuperGrid.DoCellMouseDownEvent(this, e);
                _mouseDownPoint = e.Location;
                IsDragSelection = false;
                IsDragStarted = false;
                if (_hitArea == CellArea.InContent || _hitArea == CellArea.InCellInfo)
                {
                    _mouseDownHitArea = CellArea.NoWhere;
                    if (_hitCell != null && 
                        _hitCell.CanSetActiveCell(panel) == true)
                    {
                        _mouseDownHitArea = _hitArea;
                        _mouseDownHitCell = _hitCell;
                        if (panel.SelectionGranularity == SelectionGranularity.Cell)
                        {
                            panel.LastProcessedItem = _hitCell;
                            InitSelectOrDrag(panel);
                        }
                        DoRendererMouseDown(e);
                    }
                }
            }
            base.InternalMouseDown(e);
        }
        #region DoRendererMouseDown
        private void DoRendererMouseDown(MouseEventArgs e)
        {
            if (CanModifyMerge == true)
            {
                if (_needsMouseEnter == true)
                    DoRendererMouseEnter();
                if (MouseRenderer != null)
                {
                    if (_mouseInItem == true)
                    {
                        _mouseDownInItem = true;
                        if (MouseRenderer.EditorCell != this)
                            InitializeContext(DataContext.CellMouseEvent, MouseRenderer, null);
                        MouseRenderer.OnCellMouseDown(GetControlMouseArgs(e));
                    }
                }
            }
        }
        #endregion
        #region CanSetActiveCell
        internal bool CanSetActiveCell(GridPanel panel)
        {
            GridCell acell = SuperGrid.ActiveCell;
            if (acell != this)
            {
                if (IsSelectable == false ||
                    (IsEmptyCell == true && panel.AllowEmptyCellSelection == false))
                {
                    if (SuperGrid.DoPlayingSoundEvent(panel, this, PlaySoundContext.CellActivate) == false)
                        SystemSounds.Beep.Play();
                    return (false);
                }
                GridCell ecell = SuperGrid.EditorCell;
                if (ecell != null)
                {
                    if (ecell.EndEdit() == false)
                        return (false);
                }
                if (acell != null)
                    acell.ResumeMerge(this);
                if (GridRow.IsActive == false)
                {
                    if (GridRow.CanSetActiveRow(false) == false)
                        return (false);
                    if (panel.SetActiveRow(GridRow, true) == false)
                        return (false);
                }
                if (panel.SelectionGranularity != SelectionGranularity.Row)
                {
                    if (SuperGrid.DoCellActivatingEvent(panel, acell, this) == true)
                        return (false);
                    SuperGrid.ActiveCell = this;
                    if (panel.SelectionGranularity == SelectionGranularity.Cell)
                    {
                        SuperGrid.ActiveElement = this;
                        panel.LastProcessedItem = this;
                    }
                }
            }
            return (true);
        }
        #endregion
        #region ProcessExtendSelection
        private void ProcessExtendSelection(GridPanel panel, bool extend)
        {
            bool ckey = (panel.MultiSelect == true) ?
                ((Control.ModifierKeys & Keys.Control) == Keys.Control) : false;
            if (ckey == true)
                ProcessControlExtend(panel, extend);
            else
                ProcessNonControlExtend(panel, extend);
            panel.LastProcessedItem = _hitCell;
        }
        #region ProcessControlExtend
        private void ProcessControlExtend(GridPanel panel, bool extend)
        {
            GridCell cell = panel.LastProcessedItem as GridCell;
            if (cell != null)
            {
                int startRowIndex = cell.GridRow.GridIndex;
                int startColumnIndex = panel.Columns.GetDisplayIndex(cell.GridColumn);
                int[] map = panel.Columns.DisplayIndexMap;
                if (extend == false)
                {
                    int columnIndex = map[startColumnIndex];
                    SetSelectedMerge(panel, startRowIndex,
                        startColumnIndex, startRowIndex, startColumnIndex, 0);
                    panel.SetSelectedCells(startRowIndex, columnIndex,
                        1, 1, !panel.IsCellSelected(startRowIndex, columnIndex));
                    cell.InvalidateRender();
                    panel.ColumnHeader.InvalidateRowHeader();
                }
                else
                {
                    int endRowIndex = _hitCell.GridRow.GridIndex;
                    int endColumnIndex = panel.Columns.GetDisplayIndex(_hitCell.GridColumn);
                    if (endColumnIndex - startColumnIndex != 0)
                    {
                        SelectControlColumn(panel, map,
                            startColumnIndex, endColumnIndex, startRowIndex);
                    }
                    if (endRowIndex - startRowIndex != 0)
                    {
                        SelectControlRow(panel, map,
                            startRowIndex, endRowIndex, endColumnIndex);
                    }
                }
            }
        }
        #region SelectControlColumn
        private void SelectControlColumn(GridPanel panel, int[] map,
            int startColumnIndex, int endColumnIndex, int startRowIndex)
        {
            int endRowIndex = startRowIndex;
            panel.NormalizeIndices(true,
                _anchorColumnIndex, ref startColumnIndex, ref endColumnIndex);
            panel.NormalizeIndices(false,
                _anchorRowIndex, ref startRowIndex, ref endRowIndex);
            if (endRowIndex > _anchorRowIndex)
                startRowIndex = _anchorRowIndex;
            else if (startRowIndex < _anchorRowIndex)
                endRowIndex = _anchorRowIndex;
            for (int i = startRowIndex; i <= endRowIndex; i++)
            {
                for (int j = startColumnIndex; j <= endColumnIndex; j++)
                {
                    if (j != _anchorColumnIndex)
                    {
                        int columnIndex = map[j];
                        panel.SetSelectedCells(i, columnIndex, 1, 1,
                            !panel.IsCellSelected(i, columnIndex));
                    }
                }
            }
            panel.InvalidateCells(startRowIndex,
                endRowIndex, startColumnIndex, endColumnIndex);
        }
        #endregion
        #region SelectControlRow
        private void SelectControlRow(GridPanel panel, int[] map,
            int startRowIndex, int endRowIndex, int endColumnIndex)
        {
            int startColumnIndex = endColumnIndex;
            panel.NormalizeIndices(false,
                _anchorColumnIndex, ref startColumnIndex, ref endColumnIndex);
            panel.NormalizeIndices(true,
                _anchorRowIndex, ref startRowIndex, ref endRowIndex);
            if (endColumnIndex > _anchorColumnIndex)
                startColumnIndex = _anchorColumnIndex;
            else if (startColumnIndex < _anchorColumnIndex)
                endColumnIndex = _anchorColumnIndex;
            for (int i = startRowIndex; i <= endRowIndex; i++)
            {
                for (int j = startColumnIndex; j <= endColumnIndex; j++)
                {
                    if (i != _anchorRowIndex)
                    {
                        int columnIndex = map[j];
                        panel.SetSelectedCells(i, columnIndex, 1, 1,
                            !panel.IsCellSelected(i, columnIndex));
                    }
                }
            }
            panel.InvalidateCells(startRowIndex,
                endRowIndex, startColumnIndex, endColumnIndex);
        }
        #endregion
        #endregion
        #region ProcessNonControlExtend
        private void ProcessNonControlExtend(GridPanel panel, bool extend)
        {
            bool skey = (panel.MultiSelect == true) ?
                ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) : false;
            if (skey == false ||
                panel.SelectionRowAnchor == null ||
                panel.SelectionColumnAnchor == null)
            {
                panel.SelectionRowAnchor = _mouseDownHitCell.GridRow;
                panel.SelectionColumnAnchor = _mouseDownHitCell.GridColumn;
            }
            ExtendSelection(panel, _hitCell, extend);
        }
        #endregion
        #endregion
        #region InitSelectOrDrag
        private void InitSelectOrDrag(GridPanel panel)
        {
            if (panel.SuperGrid.HasItemDragHandler == false || panel.IsItemSelected(this) == false ||
                ((Control.ModifierKeys & (Keys.Control | Keys.Shift)) != Keys.None))
            {
                ExtendSelection(panel);
            }
            else if (IsMouseDown == true)
            {
                IsDragSelection = true;
                Capture = true;
            }
        }
        #endregion
        #endregion
        #region InternalMouseUp
        internal override void InternalMouseUp(MouseEventArgs e)
        {
            if (GridColumn != null)
            {
                if (CanModifyMerge == true)
                    DoRendererMouseUp(e);
                _mouseDownInItem = false;
                SuperGrid.DoCellMouseUpEvent(this, e);
                if (InfoImageBounds.Contains(e.X, e.Y) == true)
                {
                    SuperGrid.DoCellInfoClickEvent(this, e);
                }
                else
                {
                    if (_mouseDownHitCell == this && IsMouseOver == true)
                    {
                        if (SuperGrid.DoCellClickEvent(this, e) == false)
                        {
                            GridPanel panel = GridPanel;
                            if (panel != null)
                            {
                                if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
                                {
                                    if (IsDragSelection == true)
                                        ExtendSelectionEx(panel);
                                    if (_hitArea == CellArea.InContent)
                                    {
                                        if (panel.MouseEditMode == MouseEditMode.SingleClick)
                                        {
                                            //if (Bounds.Contains(e.X, e.Y) == true)
                                            {
                                                if (CanSetActiveCell(GridPanel) == true)
                                                    BeginEdit(true);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            IsDragSelection = false;
            base.InternalMouseUp(e);
        }
        #region DoRendererMouseUp
        private void DoRendererMouseUp(MouseEventArgs e)
        {
            if (MouseRenderer != null)
            {
                if (_mouseDownInItem == true)
                {
                    if (MouseRenderer.EditorCell != this)
                        InitializeContext(DataContext.CellMouseEvent, MouseRenderer, null);
                    MouseRenderer.OnCellMouseUp(GetControlMouseArgs(e));
                    SuperGrid.Focus();
                }
            }
        }
        #endregion
        #endregion
        #region InternalMouseDoubleClick
        internal override void InternalMouseDoubleClick(MouseEventArgs e)
        {
            GridPanel panel = GridPanel;
            if (InfoImageBounds.Contains(e.X, e.Y) == true)
            {
                SuperGrid.DoCellInfoDoubleClickEvent(this, e);
            }
            else
            {
                if (SuperGrid.DoCellDoubleClickEvent(this, e) == false)
                {
                    if (_hitArea == CellArea.InContent &&
                        panel.MouseEditMode == MouseEditMode.DoubleClick)
                    {
                        if (CanSetActiveCell(panel) == true)
                        {
                            CellRange cr = GetStateCellRange();
                            if (cr != null && cr.Suspended == false)
                            {
                                if (cr.AllowSuspend == true)
                                {
                                    SuspendMerge(cr);
                                    if (_mouseDownHitCell != null)
                                    {
                                        _needsMouseEnter = true;
                                        _mouseDownHitCell.SetActive(true);
                                    }
                                }
                                else
                                {
                                    if (SuperGrid.DoPlayingSoundEvent(panel, cr, PlaySoundContext.CellActivate) == false)
                                        SystemSounds.Beep.Play();
                                }
                            }
                            else
                            {
                                BeginEdit(true);
                            }
                        }
                    }
                    _mouseDownHitCell = null;
                }
            }
        }
        #region DoRendererMouseDoubleClick
        private void DoRendererMouseDoubleClick(MouseEventArgs e)
        {
            if (CanModify == true)
            {
                if (MouseRenderer != null)
                {
                    if (_mouseDownInItem == true)
                    {
                        if (MouseRenderer.EditorCell != this)
                            InitializeContext(DataContext.CellMouseEvent, MouseRenderer, null);
                        MouseRenderer.OnCellMouseDown(GetControlMouseArgs(e));
                    }
                }
            }
        }
        #endregion
        #endregion
        #endregion
        #region GetControlMouseArgs
        private MouseEventArgs GetControlMouseArgs(MouseEventArgs e)
        {
            Rectangle r = GetAdjustedBounds(ContentBounds);
            r = GetEditPanelBounds(MouseRenderer, r);
            return (GetControlMouseArgs(e, r)); 
        }
        private MouseEventArgs
            GetControlMouseArgs(MouseEventArgs e, Rectangle r)
        {
            int x = e.X - r.X;
            int y = e.Y - r.Y;
            MouseEventArgs args = new
                MouseEventArgs(e.Button, e.Clicks, x, y, e.Delta);
            return (args);
        }
        #endregion
        #region ExtendSelection
        internal void ExtendSelection(GridPanel panel, GridCell endCell, bool extend)
        {
            if (panel.SelectionColumnAnchor is GridColumn)
            {
                int startRowIndex = panel.SelectionRowAnchor.GridIndex;
                int startColumnIndex = panel.Columns.GetDisplayIndex((GridColumn)(panel.SelectionColumnAnchor));
                int endRowIndex = endCell.GridRow.GridIndex;
                int endColumnIndex = panel.Columns.GetDisplayIndex(endCell.GridColumn);
                if (startRowIndex < 0)
                    startRowIndex = endRowIndex;
                panel.NormalizeIndices(false, 0, ref startRowIndex, ref endRowIndex);
                panel.NormalizeIndices(false, 0, ref startColumnIndex, ref endColumnIndex);
                if (startColumnIndex < 0)
                    startColumnIndex = 0;
                if (endColumnIndex < 0)
                    endColumnIndex = 0;
                if (panel.OnlyCellsSelected(
                    startRowIndex, startColumnIndex, endRowIndex, endColumnIndex) == false)
                {
                    ClearSelected(panel, extend);
                    if (startRowIndex >= 0 && endRowIndex >= 0)
                    {
                        SetSelected(panel, startRowIndex,
                            startColumnIndex, endRowIndex, endColumnIndex);
                        InvalidateSelected(panel, startRowIndex,
                            startColumnIndex, endRowIndex, endColumnIndex);
                    }
                }
            }
        }
        #region InvalidateSelected
        private void InvalidateSelected(GridPanel panel,
            int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex)
        {
            GridCell lastCell = (Control.MouseButtons == MouseButtons.None)
                ? SuperGrid.LastActiveCell : panel.LastProcessedItem as GridCell;
            if (lastCell != null)
            {
                int lastIndex = panel.Columns.GetDisplayIndex(lastCell.ColumnIndex);
                if (lastIndex < startColumnIndex)
                    startColumnIndex = lastIndex;
                else if (lastIndex > endColumnIndex)
                    endColumnIndex =lastIndex;
                if (lastCell.GridRow.GridIndex < startRowIndex)
                    startRowIndex = lastCell.GridRow.GridIndex;
                else if (lastCell.GridRow.GridIndex > endRowIndex)
                    endRowIndex = lastCell.GridRow.GridIndex;
            }
            panel.InvalidateCells(startRowIndex,
                endRowIndex, startColumnIndex, endColumnIndex);
        }
        #endregion
        #region SetSelected
        private void SetSelected(GridPanel panel,
            int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex)
        {
            SetSelectedMerge(panel, startRowIndex,
                startColumnIndex, endRowIndex, endColumnIndex, 1);
            int[] map = panel.Columns.DisplayIndexMap;
            for (int i = startColumnIndex; i <= endColumnIndex; i++)
            {
                panel.SetSelectedCells(startRowIndex, map[i],
                    endRowIndex - startRowIndex + 1, 1, true);
            }
        }
        #region SetSelectedMerge
        private void SetSelectedMerge(GridPanel panel, int startRowIndex,
            int startColumnIndex, int endRowIndex, int endColumnIndex, int selected)
        {
            if (panel.EnableCellMerging == true)
            {
                GridContainer cont = RowContainer;
                if (cont != null)
                {
                    GridContainer srow = panel.GetRowFromIndex(startRowIndex);
                    GridContainer erow = panel.GetRowFromIndex(endRowIndex);
                    if (srow != null && erow != null)
                    {
                        int sRowIndex = panel.GetRowFromIndex(startRowIndex).RowIndex;
                        int eRowIndex = panel.GetRowFromIndex(endRowIndex).RowIndex;
                        cont.SetMergeSelection(sRowIndex,
                            eRowIndex, startColumnIndex, endColumnIndex, selected);
                    }
                }
            }
        }
        #endregion
        #endregion
        #region ClearSelected
        private void ClearSelected(GridPanel panel, bool extend)
        {
            if (panel.IsGrouped == false &&
                (panel.SelectedCellCount < 50 && panel.SelectedRowCount < 10 && panel.SelectedColumnCount < 10))
            {
                foreach (GridCell cell in panel.SelectedCells)
                    cell.IsSelected = false;
                foreach (GridColumn col in panel.SelectedColumns)
                    col.IsSelected = false;
                foreach (GridContainer row in panel.SelectedRows)
                {
                    if (row != null)
                        row.IsSelected = false;
                }
                RowContainer.ClearAllMergeSelected();
            }
            else
            {
                panel.ClearAll(extend == false);
            }
            panel.SelectionClearCount++;
        }
        #endregion
        #endregion
        #region GetNextCell
        internal GridCell GetNextCell(bool canSelect)
        {
            return (GetNextCell(canSelect, true));
        }
        internal GridCell GetNextCell(bool canSelect, bool multiRow)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                int[] map = panel.Columns.DisplayIndexMap;
                int index = panel.Columns.GetDisplayIndex(GridColumn);
                int anchor = index;
                GridRow row = GridRow;
                while (row != null)
                {
                    if (row.AllowSelection == true)
                    {
                        while (++index < map.Length)
                        {
                            if (multiRow == false && index == anchor)
                                return (null);
                            GridColumn column = panel.Columns[map[index]];
                            if (column.Visible == true &&
                                (canSelect == false || column.AllowSelection == true))
                            {
                                GridCell cell = row.GetCell(
                                    column.ColumnIndex, panel.AllowEmptyCellSelection);
                                if (cell != null)
                                {
                                    if (canSelect == false || cell.AllowSelection == true)
                                        return (cell);
                                }
                            }
                        }
                    }
                    if (multiRow == true)
                        row = row.NextVisibleRow as GridRow;
                    else
                        break;
                    index = -1;
                }
            }
            return (null);
        }
        #endregion
        #region GetPreviousCell
        internal GridCell GetPreviousCell(bool canSelect)
        {
            return (GetPreviousCell(canSelect, true));
        }
        internal GridCell GetPreviousCell(bool canSelect, bool multiRow)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                int[] map = panel.Columns.DisplayIndexMap;
                int index = panel.Columns.GetDisplayIndex(GridColumn);
                int anchor = index;
                GridRow row = GridRow;
                while (row != null)
                {
                    if (row.AllowSelection == true)
                    {
                        while (--index >= 0)
                        {
                            if (multiRow == false && index == anchor)
                                return (null);
                            GridColumn column = panel.Columns[map[index]];
                            if (column.Visible == true &&
                                (canSelect == false || column.AllowSelection == true))
                            {
                                GridCell cell = row.GetCell(
                                    column.ColumnIndex, panel.AllowEmptyCellSelection);
                                if (cell != null)
                                {
                                    if (canSelect == false || cell.AllowSelection == true)
                                        return (cell);
                                }
                            }
                        }
                    }
                    if (multiRow == true)
                        row = row.PrevVisibleRow as GridRow;
                    else
                        break;
                    index = map.Length;
                }
            }
            return (null);
        }
        #endregion
        #region GetCellAreaAt
        /// 
        /// Returns element at specified mouse coordinates
        /// 
        /// Mouse event arguments
        /// Reference to child Cell element or null
        /// if no element at specified coordinates
        protected virtual CellArea GetCellAreaAt(MouseEventArgs e)
        {
            return GetCellAreaAt(e.X, e.Y);
        }
        /// 
        /// Returns element at specified mouse coordinates
        /// 
        /// Horizontal position
        /// Vertical position
        /// Reference to child element or null
        /// if no element at specified coordinates
        protected virtual CellArea GetCellAreaAt(int x, int y)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                if (InfoImageBounds.Contains(x, y) == true)
                    return (CellArea.InCellInfo);
                if (IsPrimaryCell == true)
                {
                    GridRow cellRow = GridRow;
                    if (cellRow != null)
                    {
                        Rectangle r = cellRow.ExpandButtonBounds;
                        if (cellRow.IsVFrozen == false)
                            r.Y -= VScrollOffset;
                        if (panel.IsSubPanel == true || GridColumn.IsHFrozen == false)
                            r.X -= HScrollOffset;
                        if (r.Contains(x, y) == true)
                            return (CellArea.InExpandButton);
                        r = cellRow.CheckBoxBounds;
                        if (cellRow.IsVFrozen == false)
                            r.Y -= VScrollOffset;
                        if (panel.IsSubPanel == true || GridColumn.IsHFrozen == false)
                            r.X -= HScrollOffset;
                        if (r.Contains(x, y) == true)
                            return (CellArea.InCheckBox);
                    }
                }
            }
            return (CellArea.InContent);
        }
        #endregion
        #region EnsureVisible
        ///
        /// Ensures that the given cell is visibly centered
        /// (as much as possible) in the grid display.
        ///
        ///
        public override void EnsureVisible(bool center)
        {
            if (GridRow.Visible == true && GridColumn.Visible == true)
            {
                if (IsVFrozen == false)
                    GridRow.EnsureVisible(center);
                GridColumn column = GridColumn;
                if (column != null && column.IsHFrozen == false)
                    column.EnsureVisible(center);
            }
        }
        #endregion
        #region SetActive
        ///
        /// Sets the given cell as Active
        ///
        ///true - if successful
        public bool SetActive()
        {
            return (SetActive(false));
        }
        ///
        /// Makes the given cell active and
        /// optionally selects the given cell
        ///
        ///true, if successful
        public bool SetActive(bool select)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                if (panel.SetActiveCell(this) == true)
                {
                    if (select == true)
                    {
                        panel.ClearAll();
                        IsSelected = true;
                    }
                    return (true);
                }
            }
            return (false);
        }
        #endregion
        #region Editor support
        #region GetEditControl
        internal IGridCellEditControl GetEditControl(Type type, object[] args)
        {
            if (type != null)
            {
                IGridCellEditControl editor =
                    Activator.CreateInstance(type, args) as IGridCellEditControl;
                if (editor is Control == false)
                    throw new Exception("Edit/Render Type must be based on 'Control'.");
                editor.EditorPanel = new EditorPanel();
                editor.EditorPanel.Visible = false;
                editor.EditorPanel.Controls.Add((Control) editor);
                return (editor);
            }
            return (null);
        }
        #endregion
        #region GetInternalEditControl
        internal IGridCellEditControl GetInternalEditControl()
        {
            return (GetInternalEditControl(CanModify));
        }
        internal IGridCellEditControl GetInternalEditControl(bool canModify)
        {
            if (canModify == true)
            {
                if (SuperGrid.EditorCell != this)
                {
                    Type editorType = _EditorInfo != null ? _EditorInfo.EditorType : null;
                    object[] editorParams = _EditorInfo != null ? _EditorInfo.EditorParams : null;
                    SuperGrid.DoGetEditorEvent(GridPanel, this, ref editorType, ref editorParams);
                    EditorType = editorType;
                    EditorParams = editorParams;
                }
                return (EditControl ?? (GridColumn != null ? GridColumn.EditControl : null));
            }
            return (null);
        }
        #endregion
        #region GetInternalRenderControl
        private IGridCellEditControl GetInternalRenderControl()
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                Type renderType = _EditorInfo != null ? _EditorInfo.RenderType : null;
                object[] renderParams = _EditorInfo != null ? _EditorInfo.RenderParams : null;
                SuperGrid.DoGetRendererEvent(panel, this, ref renderType, ref renderParams);
                RenderType = renderType;
                RenderParams = renderParams;
                
                return (RenderControl ?? (GridColumn != null ? GridColumn.RenderControl : null));
            }
            return (null);
        }
        #endregion
        #region BeginEdit
        ///
        /// Begins a Modal cell edit operation using
        /// the defined column or cell Modal EditControl.
        ///
        ///
        ///
        public IGridCellEditControl BeginEdit(bool selectAll)
        {
            return (BeginEdit(selectAll, null));
        }
        ///
        /// Begins a Modal cell edit operation using the defined column
        /// or cell Modal EditControl.  If a KeyEvent is provided then
        /// the event will be presented to the editor control. 
        ///
        ///Cell edit control
        public IGridCellEditControl BeginEdit(bool selectAll, KeyEventArgs e)
        {
            GridCell ecell = SuperGrid.EditorCell;
            if (ecell == this)
                return (GetInternalEditControl());
            if (ecell != null)
                throw new Exception("Modal Cell edit is already in process.");
            if (Visible == true && CanModify == true)
            {
                GridPanel.FlushSelected();
                IGridCellEditControl editor = GetInternalEditControl();
                if (editor != null && editor.CellEditMode == CellEditMode.Modal)
                {
                    if (SuspendMerge(false) == true)
                    {
                        CellVisualStyle style = GetEffectiveStyle(StyleState.Default);
                        SuperGrid.DeactivateNonModalEditor();
                        DoRendererMouseLeave(EventArgs.Empty);
                        EnsureVisible();
                        GetCurrentContentSize(style, editor);
                        InitializeContext(DataContext.CellEdit, editor, style);
                        if (SuperGrid.DoBeginEditEvent(GridPanel, this, editor) == false)
                        {
                            SuperGrid.ActiveEditor = editor;
                            SuperGrid.EditorCell = this;
                            PositionEditPanel(editor);
                            editor.EditorPanel.Show();
                            editor.EditorPanel.BringToFront();
                            if (editor.BeginEdit(selectAll) == false)
                            {
                                UpdateInfoWindow();
                                FocusEditor(editor);
                                if (e != null)
                                    SuperGrid.PressKeyDown((ushort) e.KeyCode);
                                return (editor);
                            }
                            CloseEdit(editor);
                        }
                    }
                }
            }
            return (null);
        }
        #endregion
        #region EndEdit
        ///
        /// This routine ends an in-progress Modal cell edit operation.
        ///
        ///true if ended
        public bool EndEdit()
        {
            IGridCellEditControl editor = SuperGrid.ActiveEditor;
            if (editor != null && CellEditMode == CellEditMode.Modal)
            {
                if (editor.EditorCell == this)
                {
                    if (GridRow.EditorDirty == true)
                    {
                        if (ValidateCellEdit(editor) == false)
                            return (false);
                        GridRow.EditorDirty = false;
                        object value = Value;
                        if (UpdateCellValue(editor) == true)
                            Value = value;
                    }
                    if (SuperGrid.DoEndEditEvent(GridPanel, this, editor) == false)
                    {
                        if (editor.EndEdit() == false)
                        {
                            CloseEdit(editor);
                            return (true);
                        }
                    }
                    return (false);
                }
            }
            return (true);
        }
        #region UpdateCellValue
        /// 
        /// Used by IGridCellEditControl editors to update the
        /// cell Value from the EditorValue, performing any needed
        /// data conversions for proper data typing.
        /// 
        /// 
        /// 
        public bool UpdateCellValue(IGridCellEditControl editor)
        {
            object value = editor.EditorValue;
            while (true)
            {
                try
                {
                    ConvertValueToType(editor, value);
                    return (false);
                }
                catch (Exception exp)
                {
                    bool throwException = true;
                    bool retry = false;
                    if (SuperGrid.HasDataErrorHandler == true)
                    {
                        if (SuperGrid.DoDataErrorEvent(GridPanel, this, exp,
                            DataContext.CellValueStore, ref value, ref throwException, ref retry) == true)
                        {
                            return (true);
                        }
                    }
                    if (throwException == true)
                    {
                        MessageBoxEx.Show(exp.ToString());
                        throw;
                    }
                    if (retry == false)
                        break;
                }
            }
            return (true);
        }
        #region ConvertValueToType
        private void ConvertValueToType(IGridCellEditControl editor, object value)
        {
            Type dataType = GridColumn.DataType;
            if (editor is IGridCellConvertTo)
            {
                IGridCellConvertTo cvtEditor = (IGridCellConvertTo)editor;
                object result;
                if (cvtEditor.TryConvertTo(value, dataType, out result) == true)
                {
                    Value = result;
                    return;
                }
            }
            if (dataType == null && Value != null)
                dataType = Value.GetType();
            if (dataType == typeof (SqlDateTime))
                Value = SetSqlDateTime(value);
            else if (dataType == typeof (SqlBoolean))
                Value = SetSqlBoolean(value);
            else if (dataType == typeof (SqlString))
                Value = SetSqlString(value);
            else if (dataType == typeof (SqlSingle))
                Value = SetSqlSingle(value);
            else if (dataType == typeof (SqlDouble))
                Value = SetSqlDouble(value);
            else if (dataType == typeof(SqlDecimal))
                Value = SetSqlDecimal(value);
            else if (dataType == typeof (SqlInt16))
                Value = SetSqlInt16(value);
            else if (dataType == typeof (SqlInt32))
                Value = SetSqlInt32(value);
            else if (dataType == typeof (SqlInt64))
                Value = SetSqlInt64(value);
            else if (dataType != null)
                Value = ConvertValue.ConvertTo(value, dataType);
            else
                Value = value;
        }
        #region SetSqlDateTime
        private object SetSqlDateTime(object value)
        {
            if (value == null)
                return (new SqlDateTime());
            if (value is DateTime)
                return (new SqlDateTime((DateTime)value));
            return (new SqlDateTime(Convert.ToDateTime(value)));
        }
        #endregion
        #region SetSqlBoolean
        private object SetSqlBoolean(object value)
        {
            if (value == null)
                return (new SqlBoolean());
            if (value is CheckState)
            {
                CheckState cs = (CheckState)value;
                if (cs == CheckState.Checked)
                    return (new SqlBoolean(true));
                if (cs == CheckState.Unchecked)
                    return (new SqlBoolean(false));
                return (new SqlBoolean());
            }
            return (new SqlBoolean(Convert.ToBoolean(value)));
        }
        #endregion
        #region SetSqlBoolean
        private object SetSqlString(object value)
        {
            if (value == null)
                return (new SqlString());
            return (new SqlString(Convert.ToString(value)));
        }
        #endregion
        #region SetSqlSingle
        private object SetSqlSingle(object value)
        {
            if (value == null)
                return (new SqlSingle());
            return (new SqlSingle(Convert.ToSingle(value)));
        }
        #endregion
        #region SetSqlDouble
        private object SetSqlDouble(object value)
        {
            if (value == null)
                return (new SqlDouble());
            return (new SqlSingle(Convert.ToDouble(value)));
        }
        #endregion
        #region SetSqlDecimal
        private object SetSqlDecimal(object value)
        {
            if (value == null)
                return (new SqlDecimal());
            return (new SqlDecimal(Convert.ToDecimal(value)));
        }
        #endregion
        #region SetSqlInt16
        private object SetSqlInt16(object value)
        {
            if (value == null)
                return (new SqlInt16());
            return (new SqlInt16(Convert.ToInt16(value)));
        }
        #endregion
        #region SetSqlInt32
        private object SetSqlInt32(object value)
        {
            if (value == null)
                return (new SqlInt32());
            return (new SqlInt32(Convert.ToInt32(value)));
        }
        #endregion
        #region SetSqlInt64
        private object SetSqlInt64(object value)
        {
            if (value == null)
                return (new SqlInt64());
            return (new SqlInt64(Convert.ToInt64(value)));
        }
        #endregion
        #endregion
        #endregion
        #region ValidateCellEdit
        private bool ValidateCellEdit(IGridCellEditControl editor)
        {
            try
            {
                object value = editor.EditorValue;
                object formattedValue = GetFormattedValue(editor);
                if (SuperGrid.DoCellValidatingEvent(this, ref value, formattedValue) == true)
                {
                    if (SuperGrid.DoPlayingSoundEvent(GridPanel, this, PlaySoundContext.CellValidate) == false)
                        SystemSounds.Beep.Play();
                    return (false);
                }
                editor.EditorValue = value;
                SuperGrid.DoCellValidatedEvent(this);
            }
            catch
            {
                if (SuperGrid.DoPlayingSoundEvent(GridPanel, this, PlaySoundContext.CellValidate) == false)
                    SystemSounds.Beep.Play();
                return (false);
            }
            return (true);
        }
        #endregion
        #endregion
        #region CancelEdit
        ///
        /// Cancels the current in-progress Modal cell edit operation.
        ///
        ///true if canceled
        public bool CancelEdit()
        {
            IGridCellEditControl editor = SuperGrid.ActiveEditor;
            if (editor == null || CellEditMode != CellEditMode.Modal)
                throw new Exception("Bad CancelEdit - Modal edit not in progress.");
            if (SuperGrid.DoCancelEditEvent(GridPanel, this, editor) == false)
            {
                if (editor.CancelEdit() == false)
                {
                    bool rowDirty = GridRow.RowDirty;
                    bool needsStored = GridRow.RowNeedsStored;
                    CloseEdit(editor);
                    GridRow.RowDirty = rowDirty;
                    GridRow.RowNeedsStored = needsStored;
                    return (true);
                }
            }
            return (true);
        }
        #endregion
        #region CloseEdit
        private void CloseEdit(IGridCellEditControl editor)
        {
            CloseCellInfoWindow();
            IsMouseOver = false;
            bool wasFocused = ((Control)editor).ContainsFocus;
            editor.EditorPanel.Hide();
            editor.EditorPanel.GridCell = null;
            GridRow.EditorDirty = false;
            SuperGrid.ActiveEditor = null;
            SuperGrid.EditorCell = null;
            if (wasFocused == true)
                SuperGrid.Focus();
            SuperGrid.DoCloseEditEvent(GridPanel, this);
            if (GridPanel == null || GridPanel.NeedToUpdateDataFilter == true)
                InvalidateLayout();
            else
                InvalidateRender();
            SuperGrid.Update();
        }
        #endregion
        #region PositionEditPanel
        internal void PositionEditPanel(IGridCellEditControl editor)
        {
            PositionEditControl(editor);
            UpdateCellInfoWindowPos();
            ((Control)editor).Update();
            editor.EditorPanel.Update();
        }
        #endregion
        #region PostCellKeyDown
        ///
        /// PostCellKeyDown
        ///
        ///
        internal void PostCellKeyDown(Keys keyData)
        {
            if (CanModifyMerge == true)
            {
                SuperGrid.DeactivateNonModalEditor();
                IGridCellEditControl editor = GetInternalEditControl();
                if (editor != null)
                {
                    KeyEventArgs e = new KeyEventArgs(keyData);
                    CellVisualStyle style = GetEffectiveStyle();
                    InitializeContext(DataContext.CellKeyEvent, editor, style);
                    editor.CellKeyDown(e);
                }
                PostInternalMouseMove();
            }
        }
        #endregion
        #region PositionEditControl
        ///
        /// PositionEditControl
        ///
        ///
        private void PositionEditControl(IGridCellEditControl editor)
        {
            if (GridColumn != null)
            {
                GridPanel panel = GridPanel;
                if (panel != null)
                {
                    Control c = (Control) editor;
                    Rectangle r = GetAdjustedBounds(ContentBounds);
                    Rectangle e = GetEditPanelBounds(editor, r);
                    e = GetClippedBounds(panel, e);
                    switch (editor.CellEditMode)
                    {
                        case CellEditMode.Modal:
                        case CellEditMode.NonModal:
                            if (GetCellHighlightMode(panel) == CellHighlightMode.Content)
                            {
                                r = GetEditPanelBounds(editor, r);
                                e = GetClippedBounds(panel, r);
                            }
                            editor.EditorPanel.Bounds = e;
                            c.Bounds = GetEditorBounds(editor, r, e);
                            editor.EditorPanel.SizeEx = Bounds.Size;
                            editor.EditorPanel.OffsetEx = new Point(Bounds.X - e.X, Bounds.Y - e.Y);
                            if (editor.CellEditMode == CellEditMode.NonModal)
                            {
                                editor.EditorPanel.BringToFront();
                                editor.EditorPanel.Show();
                            }
                            break;
                        case CellEditMode.InPlace:
                            r.Intersect(SuperGrid.SViewRect);
                            r.Location = Point.Empty;
                            c.Bounds = r;
                            break;
                    }
                }
            }
        }
        #region GetEditPanelBounds
        private Rectangle GetEditPanelBounds(IGridCellEditControl editor, Rectangle r)
        {
            CellVisualStyle style = GetEffectiveStyle();
            int n = r.Right;
            if (SuperGrid.EditorCell != this)
            {
                AlignHorizontally(editor, style, ref r);
            }
            else
            {
                if (GetCellHighlightMode(GridPanel) == CellHighlightMode.Content)
                    n -= 2;
            }
            if (r.Right > n)
                r.Width -= (r.Right - n);
            n = r.Bottom - 1;
            AlignVertically(editor, style, ref r);
            if (r.Bottom > n)
                r.Height -= (r.Bottom - n);
            return (r);
        }
        #endregion
        #region AlignHorizontally
        private void AlignHorizontally(
            IGridCellEditControl editor, CellVisualStyle style, ref Rectangle r)
        {
            Size size = _ContentSize;
            switch (editor.StretchBehavior)
            {
                case StretchBehavior.Both:
                case StretchBehavior.HorizontalOnly:
                    size.Width = r.Width;
                    break;
                default:
                    if (size.Width <= 0)
                    {
                        GetCurrentContentSize(style, editor);
                        size = _ContentSize;
                    }
                    if (size.Width <= 0)
                    {
                        size.Width = r.Width;
                    }
                    else if (r.Width > size.Width)
                    {
                        switch (style.Alignment)
                        {
                            case Alignment.TopCenter:
                            case Alignment.MiddleCenter:
                            case Alignment.BottomCenter:
                                r.X += ((r.Width - size.Width) / 2);
                                break;
                            case Alignment.TopRight:
                            case Alignment.MiddleRight:
                            case Alignment.BottomRight:
                                r.X += (r.Width - size.Width - 1);
                                break;
                        }
                    }
                    break;
            }
            r.Width = size.Width;
        }
        #endregion
        #region AlignVertically
        private void AlignVertically(
            IGridCellEditControl editor, CellVisualStyle style, ref Rectangle r)
        {
            Size size = _ContentSize;
            switch (editor.StretchBehavior)
            {
                case StretchBehavior.Both:
                case StretchBehavior.VerticalOnly:
                    size.Height = r.Height;
                    break;
                default:
                    if (size.Height <= 0)
                    {
                        size.Height = r.Height;
                    }
                    else if (r.Height > size.Height)
                    {
                        switch (style.Alignment)
                        {
                            case Alignment.MiddleLeft:
                            case Alignment.MiddleCenter:
                            case Alignment.MiddleRight:
                                r.Y += ((r.Height - size.Height)/2);
                                break;
                            case Alignment.BottomLeft:
                            case Alignment.BottomCenter:
                            case Alignment.BottomRight:
                                r.Y += r.Height - size.Height;
                                break;
                        }
                    }
                    break;
            }
            r.Height = size.Height;
        }
        #endregion
        #region GetEditorBounds
        private Rectangle GetEditorBounds(
            IGridCellEditControl editor, Rectangle r, Rectangle e)
        {
            if (GetCellHighlightMode(GridPanel) == CellHighlightMode.Content)
            {
                r.X = 0;
                r.Y = 0;
            }
            else
            {
                r.X = (r.X - e.X);
                r.Y = (r.Y - e.Y);
                r = GetEditPanelBounds(editor, r);
            }
            return (r);
        }
        #endregion
        #endregion
        #region FocusEditor
        internal void FocusEditor(IGridCellEditControl editor)
        {
            if (((Control)editor).Focused == false)
                ((Control)editor).Focus();
            if (editor is IGridCellEditorFocus)
                ((IGridCellEditorFocus)editor).FocusEditor();
        }
        #endregion
        #region CellRender
        ///
        /// This routine can be called by a cell editor / renderer to
        /// perform default cell rendering provided by the grid.
        ///
        ///
        ///
        public void CellRender(IGridCellEditControl editor, Graphics g)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                CellVisualStyle style = GetEffectiveStyle();
                CellRange cr = GetStateCellRange();
                Rectangle bounds = (cr != null) ? GetBounds(panel, cr.BackBounds) : Bounds;
                Rectangle rc = GetAdjustedBounds(GetContentBounds(panel, bounds));
                if (rc.Height > 0 && rc.Width > 0)
                {
                    RenderContent(g, panel, editor, style, rc, cr);
                    RenderCellInfo(g, panel);
                }
            }
        }
        #region RenderContent
        private void RenderContent(Graphics g, GridPanel panel,
            IGridCellEditControl editor, CellVisualStyle style, Rectangle rc, CellRange cr)
        {
            if (cr != null &&
                (editor.CellEditMode == CellEditMode.Modal || cr.AlwaysDisplayFormattedValue == true))
                RenderRangeContent(g, panel, style, rc, cr);
            else
                RenderCellContent(g, editor, style, rc);
        }
        #region RenderRangeContent
        private void RenderRangeContent(Graphics g,
            GridPanel panel, CellVisualStyle style, Rectangle rc, CellRange cr)
        {
            string s = cr.FormattedValue;
            if (string.IsNullOrEmpty(s) == false)
            {
                if (panel.EnableCellRangeMarkup == true)
                {
                    if (MarkupParser.IsMarkup(s) == true)
                    {
                        BodyElement markup = MarkupParser.Parse(s);
                        RenderTextMarkup(g, markup, style, rc);
                    }
                }
                else
                {
                    eTextFormat tf = style.GetTextFormatFlags();
                    TextDrawing.DrawString(g, s, style.Font, style.TextColor, rc, tf);
                }
            }
        }
        #region RenderTextMarkup
        private void RenderTextMarkup(Graphics g,
            BodyElement textMarkup, CellVisualStyle style, Rectangle r)
        {
            MarkupDrawContext d =
                new MarkupDrawContext(g, style.Font, style.TextColor, false);
            textMarkup.Arrange(new Rectangle(r.Location, r.Size), d);
            Size size = textMarkup.Bounds.Size;
            switch (style.Alignment)
            {
                case Alignment.MiddleLeft:
                case Alignment.MiddleCenter:
                case Alignment.MiddleRight:
                    if (r.Height > size.Height)
                        r.Y += (r.Height - size.Height) / 2;
                    break;
                default:
                    if (r.Height > size.Height)
                        r.Y = r.Bottom - size.Height;
                    break;
            }
            textMarkup.Bounds = new Rectangle(r.Location, size);
            Region oldClip = g.Clip;
            try
            {
                g.SetClip(r, CombineMode.Intersect);
                textMarkup.Render(d);
            }
            finally
            {
                g.Clip = oldClip;
            }
        }
        #endregion
        #endregion
        #region RenderCellContent
        private void RenderCellContent(Graphics g,
            IGridCellEditControl editor, CellVisualStyle style, Rectangle rc)
        {
            switch (editor.CellEditMode)
            {
                case CellEditMode.Modal:
                    string s = GetFormattedValueEx(editor);
                    eTextFormat tf = style.GetTextFormatFlags();
                    if (string.IsNullOrEmpty(s) == false)
                        TextDrawing.DrawString(g, s, style.Font, style.TextColor, rc, tf);
                    break;
                case CellEditMode.NonModal:
                case CellEditMode.InPlace:
                    Rectangle re = GetEditPanelBounds(editor, rc);
                    if (re.Width > 0 && re.Height > 0)
                    {
                        Bitmap bm = GetCellBitmap(editor, rc);
                        if (bm != null)
                        {
                            PaintButtonContent(editor, bm, rc, re);
                            g.DrawImageUnscaledAndClipped(bm, re);
                        }
                    }
                    break;
            }
        }
        #endregion
        #endregion
        #region RenderCellInfo
        private void RenderCellInfo(Graphics g, GridPanel panel)
        {
            if (ShowInfoCellImage(panel) == true)
            { 
                Image image = GetInfoImage();
                if (image != null)
                {
                    Rectangle rc = InfoImageBounds;
                    if (rc.Width > 0 && rc.Height > 0)
                        g.DrawImageUnscaledAndClipped(image, rc);
                }
            }
        }
        #region ShowInfoCellImage
        private bool ShowInfoCellImage(GridPanel panel)
        {
            if (panel.ShowCellInfo == false || _InfoText == null)
                return (false);
            if (_InfoText.Equals("") == false)
                return (true);
            return (panel.ShowCellInfoDisplayMode == ShowCellInfoDisplayMode.ShowWithEmptyText);
        }
        #endregion
        #endregion
        #region GetExpValue
        ///
        /// Gets the resultant value of the evaluated Cell Expression, if
        /// applicable. Otherwise returns the given value.
        ///
        ///
        ///
        public string GetExpValue(string source)
        {
            GridPanel panel = GridPanel;
            if (IsValueExpression == true &&
                panel.EnableCellExpressions == true)
            {
                EEval eval = panel.ExpDictionary[this];
                if (eval != null)
                {
                    while (true)
                    {
                        try
                        {
                            _ExpValue = eval.Evaluate();
                            string s = (_ExpValue != null)
                                           ? _ExpValue.ToString()
                                           : "";
                            InfoText = null;
                            return (s);
                        }
                        catch (Exception exp)
                        {
                            bool retry = false;
                            bool throwException = false;
                            if (SuperGrid.HasDataErrorHandler == true)
                            {
                                object value = _Value;
                                if (SuperGrid.DoDataErrorEvent(panel, this, exp,
                                   DataContext.CellExpressionEval, ref value, ref throwException, ref retry) == true)
                                {
                                    return (source);
                                }
                            }
                            if (throwException == true)
                                throw;
                            InfoText = exp.Message;
                            if (retry == false)
                                return ("####!");
                        }
                    }
                }
            }
            return (source);
        }
        #endregion
        #region GetCellBitmap
        /// 
        /// Gets the cell paint bitmap
        /// 
        /// 
        /// 
        /// 
        private Bitmap GetCellBitmap(IGridCellEditControl editor, Rectangle r)
        {
            Bitmap bm = editor.EditorCellBitmap;
            if (bm == null || bm.Size != r.Size)
            {
                if (bm != null)
                    bm.Dispose();
                bm = new Bitmap(r.Width, r.Height);
                editor.EditorCellBitmap = bm;
            }
            return (bm);
        }
        #endregion
        #region PaintButtonContent
        /// 
        /// Paints the button background and content
        /// 
        private void PaintButtonContent(IGridCellEditControl editor,
            Bitmap bm, Rectangle rc, Rectangle re)
        {
            Control c = (Control)editor;
            // SizeEx is the size of the Adjusted Content size of the cell
            // OffsetEx is the offset from the Editor panel to the cell ContentBounds.
            editor.EditorPanel.Size = re.Size;
            editor.EditorPanel.SizeEx = rc.Size;
            editor.EditorPanel.OffsetEx = new Point(rc.X - re.X, rc.Y - re.Y);
            // Set the control bounds and initiate the
            // transfer of the control image to our bitmap.
            re.Location = Point.Empty;
            editor.SuspendUpdate = true;
            if (editor.EditorPanel.IsHandleCreated == false)
            {
                editor.EditorPanel.Show();
                editor.EditorPanel.BringToFront();
                editor.EditorPanel.Hide();
            }
            c.Bounds = re;
            c.DrawToBitmap(bm, re);
            editor.SuspendUpdate = false;
        }
        #endregion
        #endregion
        #region PaintEditorBackground
        ///
        /// Performs default cell background painting for the cell.
        ///
        ///
        ///
        public void PaintEditorBackground(PaintEventArgs e, IGridCellEditControl editor)
        {
            Rectangle r = new Rectangle();
            r.Size = editor.EditorPanel.SizeEx;
            r.Location = Point.Empty;
            if (r.Width > 0 && r.Height > 0)
            {
                Graphics g = e.Graphics;
                if (SuperGrid.DoPreRenderCellEvent(g, this, RenderParts.Background, r) == false)
                {
                    GridPanel panel = GridPanel;
                    CellHighlightMode mode = GetCellHighlightMode(panel);
                    using (Brush br = GetContentBrush(panel, r, mode))
                        g.FillRectangle(br, r);
                    SuperGrid.DoPostRenderCellEvent(g, this, RenderParts.Background, r);
                }
            }
        }
        #endregion
        #region ExtendSelection
        ///
        /// ExtendSelection
        ///
        internal void ExtendSelection(GridPanel panel)
        {
            if (IsMouseSelectable() == true)
            {
                Capture = true;
                ExtendSelectionEx(panel);
            }
        }
        private void ExtendSelectionEx(GridPanel panel)
        {
            _mouseDownHitCell = this;
            _mouseDownHitArea = CellArea.InContent;
            if (panel.SelectionRowAnchor == null)
                panel.SelectionRowAnchor = GridRow;
            if (_hitCell != null)
            {
                _anchorRowIndex = _hitCell.GridRow.GridIndex;
                _anchorColumnIndex = panel.Columns.GetDisplayIndex(GridColumn);
                ProcessExtendSelection(panel, false);
                if (panel.LastProcessedItem != _hitCell)
                    GridRow.EditorDirty = false;
                if (SuperGrid.ActiveNonModalEditor != null)
                {
                    SuperGrid.Update();
                    if (SuperGrid.ActiveNonModalEditor != null)
                        SuperGrid.ActiveNonModalEditor.EditorPanel.Invalidate(true);
                }
            }
        }
        #region IsMouseSelectable
        private bool IsMouseSelectable()
        {
            if ((Control.MouseButtons & MouseButtons.Left) == MouseButtons.Left)
                return (true);
            return (IsSelected == false);
        }
        #endregion
        #endregion
        #region InitializeContext
        private void InitializeContext(DataContext dataContext,
            IGridCellEditControl editor, CellVisualStyle style)
        {
            if (((Control) editor).Handle != null)
            {
                object value = Value;
                if (InitializeContextEx(dataContext, editor, style) == true)
                    Value = value;
            }
        }
        private bool InitializeContextEx(DataContext dataContext,
            IGridCellEditControl editor, CellVisualStyle style)
        {
            object value = Value;
            while (true)
            {
                bool suspended = editor.SuspendUpdate;
                try
                {
                    IsDataError = false;
                    editor.SuspendUpdate = true;
                    editor.EditorPanel.GridCell = this;
                    editor.InitializeContext(this, style);
                    SuperGrid.DoInitEditContextEvent(this, editor);
                    return (false);
                }
                catch (Exception exp)
                {
                    bool retry = false;
                    bool throwException = false;
                    if (SuperGrid.HasDataErrorHandler == true)
                    {
                        if (SuperGrid.DoDataErrorEvent(GridPanel, this, exp,
                            dataContext, ref value, ref throwException, ref retry) == true)
                        {
                            return (true);
                        }
                    }
                    else
                    {
                        IsDataError = true;
                        return (false);
                    }
                    if (throwException == true)
                        throw;
                    if (retry == false)
                        break;
                    Value = value;
                }
                finally
                {
                    editor.SuspendUpdate = suspended;
                }
            }
            return (true);
        }
        #endregion
        #region CellRender
        private void CellRender(Graphics g,
            CellVisualStyle style, IGridCellEditControl renderer)
        {
            if (renderer.CellEditMode != CellEditMode.Modal)
            {
                try
                {
                    renderer.SuspendUpdate = true;
                    InitializeContext(DataContext.CellRender, renderer, style);
                    renderer.CellRender(g);
                }
                finally
                {
                    renderer.SuspendUpdate = false;
                }
            }
            else
            {
                InitializeContext(DataContext.CellRender, renderer, style);
                renderer.CellRender(g);
            }
        }
        #endregion
        #region SetEditorDirty
        ///
        /// Called by the cell editor to conditionally set
        /// the cells row level EditorDirty state.
        ///
        ///
        public void SetEditorDirty(IGridCellEditControl editor)
        {
            if (GridColumn.MarkRowDirtyOnCellValueChange == true)
            {
                if (SuperGrid.DoRowMarkedDirtyEvent(this, editor) == false)
                    EditorDirty = true;
            }
        }
        #endregion
        #region EditorValueChanged
        ///
        /// This routine is called by cell editors to signal to the grid
        /// that the editor has changed the cell Value.
        ///
        ///
        public void EditorValueChanged(IGridCellEditControl editor)
        {
            if (editor.SuspendUpdate == false)
            {
                SuperGrid.DoEditorValueChangedEvent(this, editor);
                editor.EditorValueChanged = true;
            }
        }
        #endregion
        #endregion
        #region UpdateBoundingRects
        private void UpdateBoundingRects()
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                _BoundsUpdateCount = SuperGrid.BoundsUpdateCount;
                _BackBounds = GetBackBounds(panel);
                _Bounds = GetBounds(panel);
            }
        }
        #region GetBackBounds
        /// 
        /// Gets the scroll adjusted background bounding rectangle
        /// 
        /// 
        /// 
        internal Rectangle GetBackBounds(GridPanel panel)
        {
            Rectangle r = BoundsRelative;
            if (panel.IsSubPanel == false)
            {
                GridColumn column = GridColumn;
                if (column != null)
                {
                    if (column.IsHFrozen == false)
                        r.X -= HScrollOffset;
                }
            }
            else
            {
                r.X -= HScrollOffset;
            }
            if (GridRow.IsVFrozen == false)
                r.Y -= VScrollOffset;
            return (r);
        }
        #endregion
        #region GetBounds
        internal Rectangle GetBounds(GridPanel panel)
        {
            return (GetBounds(panel, BackBounds));
        }
        /// 
        /// Gets the scroll adjusted bounding rectangle
        /// 
        /// 
        /// 
        /// 
        internal Rectangle GetBounds(GridPanel panel, Rectangle backBounds)
        {
            Rectangle r = backBounds;
            r.Y += GridRow.EffectivePreDetailRowHeight;
            r.Height -= (GridRow.EffectivePreDetailRowHeight + GridRow.EffectivePostDetailRowHeight);
            return (r);
        }
        #endregion
        #region GetCellBounds
        /// 
        /// Gets the SViewRect clipped Bounds
        /// 
        /// 
        /// 
        private Rectangle GetCellBounds(GridPanel panel)
        {
            return (GetClippedBounds(panel, Bounds));
        }
        #endregion
        #region GetContentBounds
        internal Rectangle GetContentBounds(GridPanel panel)
        {
            return (GetContentBounds(panel, Bounds));
        }
        /// 
        /// Gets the cell content (excludes image) bounding rectangle
        /// 
        /// 
        /// 
        /// 
        internal Rectangle GetContentBounds(GridPanel panel, Rectangle bounds)
        {
            Rectangle r = bounds;
            int n = Dpi.Width(panel.LevelIndentSize.Width * _IndentLevel);
            CellRange cr = GetStateCellRange();
            if (HasPrimaryCell(panel, cr) == true)
            {
                if (panel.ShowTreeButtons == true || panel.ShowTreeLines == true)
                    n += panel.TreeButtonIndent;
                if (panel.CheckBoxes == true)
                    n += Dpi.Width(panel.CheckBoxSize.Width + (CheckBoxSpacing * 2));
                if (Merged == true)
                {
                    GridColumn col = panel.Columns.ColumnAtDisplayIndex(cr.ColumnStart);
                    n = Math.Max(n - (r.X - col.Bounds.X), 0);
                }
                r.X += n;
                r.Width -= n;
            }
            else if (panel.GroupColumns.Count > 0)
            {
                if (panel.Columns.FirstVisibleColumn == GridColumn)
                {
                    r.X += n;
                    r.Width -= n;
                }
            }
            CellVisualStyle style = GetEffectiveStyle();
            object figure = style.GetFigure(panel);
            if (figure != null)
                r = style.GetNonFigureBounds(panel, r);
            if (GridColumn.InfoImageOverlay == false)
            {
                if (string.IsNullOrEmpty(InfoText) == false)
                {
                    Image image = GetInfoImage();
                    if (image != null)
                    {
                        switch (GridColumn.InfoImageAlignment)
                        {
                            case Alignment.MiddleLeft:
                                r.X += (image.Size.Width + 4);
                                r.Width -= (image.Size.Width + 4);
                                break;
                            case Alignment.MiddleRight:
                                r.Width -= (image.Size.Width + 4);
                                break;
                        }
                    }
                }
            }
            r.Inflate(-1, -1);
            return (r);
        }
        #region IsPrimaryCell
        private bool HasPrimaryCell(GridPanel panel, CellRange cr)
        {
            if (cr != null)
                return (cr.ColumnStart == panel.Columns.GetDisplayIndex(panel.PrimaryColumn));
            return (panel.PrimaryColumnIndex == _ColumnIndex);
        }
        #endregion
        #endregion
        #region GetEditBounds
        /// 
        /// Gets 
        /// 
        /// 
        /// 
        private Rectangle GetEditBounds(GridPanel panel)
        {
            Rectangle r = GetClippedBounds(panel, ContentBounds);
            r.Inflate(-1, -1);
            return (r);
        }
        #endregion
        #region GetClippedBounds
        private Rectangle GetClippedBounds(GridPanel panel, Rectangle r)
        {
            Rectangle v = SViewRect;
            if (IsVFrozen == true)
            {
                int n = panel.FixedRowHeight - panel.FixedHeaderHeight;
                v.Y -= n;
                v.Height += n;
            }
            if (GridColumn.IsHFrozen == false)
            {
                GridColumn pcol = panel.Columns.GetLastVisibleFrozenColumn();
                if (pcol != null)
                {
                    int n = Dpi.Width(pcol.BoundsRelative.Right - v.X);
                    v.X += n;
                    v.Width -= n;
                }
            }
            r.Intersect(v);
            return (r);
        }
        #endregion
        #endregion
        #region GetAdjustedBounds
        #region GetAdjustedBounds()
        private Rectangle GetAdjustedBounds()
        {
            Rectangle r = Bounds;
            switch (GridPanel.GridLines)
            {
                case GridLines.Both:
                    r.Width -= Dpi.Width1;
                    r.Height -= Dpi.Height1;
                    break;
                case GridLines.Vertical:
                    r.Width -= Dpi.Width1;
                    break;
                case GridLines.Horizontal:
                    r.Height -= Dpi.Height1;
                    break;
            }
            return (r);
        }
        #endregion
        #region GetAdjustedBounds(r)
        private Rectangle GetAdjustedBounds(Rectangle r)
        {
            CellVisualStyle style = GetEffectiveStyle();
            r.X += Dpi.Width(style.BorderThickness.Left + style.Margin.Left + style.Padding.Left);
            r.Width -= Dpi.Width(style.BorderThickness.Horizontal + style.Margin.Horizontal + style.Padding.Horizontal);
            r.Y += Dpi.Height(style.BorderThickness.Top + style.Margin.Top + style.Padding.Top);
            r.Height -= Dpi.Height(style.BorderThickness.Vertical + style.Margin.Vertical + style.Padding.Vertical);
            r.Width--;
            return (r);
        }
        #endregion
        #endregion
        #region GetCurrentContentSize
        private void GetCurrentContentSize(
            CellVisualStyle style, IGridCellEditControl editor)
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                Size oldSize = _ContentSize;
                int width = Bounds.Size.Width;
                object figure = style.GetFigure(panel);
                if (figure != null)
                {
                    Alignment alignment = style.ImageAlignment;
                    if (style.IsOverlayImage == true)
                        alignment = Alignment.MiddleCenter;
                    switch (alignment)
                    {
                        case Alignment.TopLeft:
                        case Alignment.TopRight:
                        case Alignment.MiddleLeft:
                        case Alignment.MiddleRight:
                        case Alignment.BottomLeft:
                        case Alignment.BottomRight:
                            width -= style.GetFigureSize(panel).Width;
                            break;
                    }
                }
                width -= (style.GetBorderSize(true).Width + 2);
                Size constraintSize = new Size(width, 0);
                using (Graphics g = SuperGrid.CreateGraphics())
                    _ContentSize = GetProposedSize(g, style, constraintSize, editor, CellSizingSource.ActualAndFormattedValues);
                if (_ContentSize != oldSize)
                    _BoundsUpdateCount = (ushort)(SuperGrid.BoundsUpdateCount - 1);
            }
        }
        #endregion
        #region GetCellEditBounds
        ///
        /// Get the CellEditBounds for the cell.
        ///
        ///
        ///
        public Rectangle GetCellEditBounds(IGridCellEditControl editor)
        {
            Rectangle r = GetAdjustedBounds(ContentBounds);
            r = GetEditPanelBounds(editor, r);
            return (r);
        }
        #endregion
        #region GetFormattedValue
        internal string GetFormattedValue()
        {
            IGridCellEditControl editor = SuperGrid.EditorCell == this
                ? GetInternalEditControl() : GetInternalRenderControl();
            return (GetFormattedValue(editor));
        }
        internal string GetFormattedValue(IGridCellEditControl editor)
        {
            string s = null;
            if (editor == null || IsDataError == true)
            {
                if (_Value != null)
                    s = _Value.ToString();
            }
            else
            {
                bool suspended = editor.SuspendUpdate;
                try
                {
                    editor.SuspendUpdate = true;
                    if (SuperGrid.EditorCell != this)
                        InitializeContext(DataContext.CellGetFormattedValue, editor, null);
                    s = editor.EditorFormattedValue;
                }
                finally
                {
                    editor.SuspendUpdate = suspended;
                }
                if (s != null && s.TrimStart().StartsWith("=") == true)
                    s = GetExpValue(s);
            }
            CellSizingSource sizingSource = CellSizingSource.ActualAndFormattedValues;
            SuperGrid.DoGetCellFormattedValueEvent(this, ref s, ref sizingSource);
            return (s ?? "");
        }
        internal string GetFormattedValueEx(IGridCellEditControl editor)
        {
            string s = null;
            if (editor == null || IsDataError == true)
            {
                if (_Value != null)
                    s = _Value.ToString();
            }
            else
            {
                s = editor.EditorFormattedValue;
                if (s != null && s.TrimStart().StartsWith("=") == true)
                    s = GetExpValue(s);
            }
            CellSizingSource sizingSource = CellSizingSource.ActualAndFormattedValues;
            SuperGrid.DoGetCellFormattedValueEvent(this, ref s, ref sizingSource);
            return (s ?? "");
        }
        #endregion
        #region CellInfoWindow support
        #region UpdateInfoWindow
        private void UpdateInfoWindow()
        {
            GridPanel panel = GridPanel;
            if (panel != null)
            {
                if (SuperGrid.EditorCell != this)
                {
                    CloseCellInfoWindow();
                }
                else
                {
                    if (GridColumn.InfoImageOverlay == false)
                    {
                        if (SuperGrid.ActiveEditor != null)
                            PositionEditPanel(SuperGrid.ActiveEditor);
                    }
                    else
                    {
                        if (CanShowCellInfo(panel) == true)
                        {
                            if (_cellInfoWindow == null)
                                OpenCellInfoWindow();
                            UpdateCellInfoWindowPos();
                            _cellInfoWindow.Show();
                            _cellInfoWindow.BringToFront();
                        }
                        else
                        {
                            CloseCellInfoWindow();
                        }
                    }
                }
            }
        }
        #endregion
        #region CanShowCellInfo
        private bool CanShowCellInfo(GridPanel panel)
        {
            if (ShowInfoCellImage(panel) == true)
                return (GetInfoImage() != null);
                
            return (false);
        }
        #endregion
        #region UpdateCellInfoWindowPos
        private void UpdateCellInfoWindowPos()
        {
            if (_cellInfoWindow != null)
            {
                if (_cellInfoWindow != null)
                {
                    Point pt = InfoImageBounds.Location;
                    pt = SuperGrid.PointToScreen(pt);
                    if (SuperGrid.ActiveEditor != null)
                        pt = SuperGrid.ActiveEditor.EditorPanel.PointToClient(pt);
                    else if (SuperGrid.ActiveNonModalEditor != null)
                        pt = SuperGrid.ActiveNonModalEditor.EditorPanel.PointToClient(pt);
                    _cellInfoWindow.Location = pt;
                }
            }
        }
        #endregion
        #region OpenCellInfoWindow
        private void OpenCellInfoWindow()
        {
            _cellInfoWindow = new CellInfoWindow(SuperGrid, this);
            _cellInfoWindow.Parent = SuperGrid.ActiveEditor.EditorPanel;
            SuperGrid.ActiveEditor.EditorPanel.Controls.Add(_cellInfoWindow);
        }
        #endregion
        #region CloseCellInfoWindow
        private void CloseCellInfoWindow()
        {
            if (_cellInfoWindow != null)
            {
                SuperGrid.ToolTipText = "";
                _cellInfoWindow.Dispose();
                _cellInfoWindow = null;
            }
        }
        #endregion
        #endregion
        #region Style support
        #region GetEffectiveStyle
        ///
        /// Gets the EffectiveStyle for the cell. The effective
        /// style is the cached, composite style definition for the
        /// given cell, composed from panel, row, column, and cell styles.
        ///
        ///
        public CellVisualStyle GetEffectiveStyle()
        {
            bool selected = IsSelected;
            StyleState cellState = GetCellState(selected);
            CellVisualStyle style = GetEffectiveStyle(cellState);
            return (style);
        }
        ///
        /// Gets the EffectiveStyle for the cell- for the given StyleType.
        /// The effective style is the cached, composite style definition for the
        /// given cell, composed from panel, row, column, and cell styles.
        ///
        ///
        ///
        public CellVisualStyle GetEffectiveStyle(StyleType type)
        {
            ValidateStyle();
            return (GetStyle(type));
        }
        internal CellVisualStyle GetEffectiveStyle(bool selected)
        {
            StyleState cellState = GetCellState(selected);
            return (GetEffectiveStyle(cellState));
        }
        private CellVisualStyle GetEffectiveStyle(StyleState cellState)
        {
            ValidateStyle();
            if (IsDesignerHosted == true)
                cellState &= ~(StyleState.MouseOver | StyleState.Selected);
            CellRange cr = GetStateCellRange();
            if (cr != null)
                return (cr.GetEffectiveStyle(RowContainer, cellState));
            if (IsEmptyCell == true &&
                (GridPanel.AllowEmptyCellSelection == false || cellState == StyleState.Default))
            {
                return (GetStyle(StyleType.Empty));
            }
            if (IsSelectable == false)
                return (GetStyle(StyleType.NotSelectable));
            switch (cellState)
            {
                case StyleState.MouseOver:
                    return (GetStyle(StyleType.MouseOver));
                case StyleState.Selected:
                    return (GetStyle(StyleType.Selected));
                case StyleState.Selected | StyleState.MouseOver:
                    return (GetStyle(StyleType.SelectedMouseOver));
                case StyleState.ReadOnly:
                    return (GetStyle(StyleType.ReadOnly));
                case StyleState.ReadOnly | StyleState.MouseOver:
                    return (GetStyle(StyleType.ReadOnlyMouseOver));
                case StyleState.ReadOnly | StyleState.Selected:
                    return (GetStyle(StyleType.ReadOnlySelected));
                case StyleState.ReadOnly | StyleState.MouseOver | StyleState.Selected:
                    return (GetStyle(StyleType.ReadOnlySelectedMouseOver));
                default:
                    return (GetStyle(StyleType.Default));
            }
        }
        #endregion
        #region GetCellState
        private StyleState GetCellState(bool selected)
        {
            StyleState cellState = StyleState.Default;
            if (IsReadOnly == true)
                cellState |= StyleState.ReadOnly;
            if (SuperGrid.EditorCell != null || SuperGrid.NonModalEditorCell != null)
            {
                if (SuperGrid.EditorCell == this || SuperGrid.NonModalEditorCell == this)
                    cellState |= StyleState.MouseOver;
            }
            else
            {
                if (CapturedItem == null || CapturedItem is GridCell)
                {
                    Point pt = SuperGrid.PointToClient(Control.MousePosition);
                    Rectangle r = Bounds;
                    GridPanel panel = GridPanel;
                    if (Merged == true)
                    {
                        CellRange cr = GetStateCellRange();
                        if (cr != null)
                            r = GetBounds(panel, cr.BackBounds);
                    }
                    Rectangle t = ViewRect;
                    r.Intersect(t);
                    if (r.Contains(pt) == true)
                        cellState |= StyleState.MouseOver;
                }
            }
            if (selected == true)
                cellState |= StyleState.Selected;
            return (cellState);
        }
        #endregion
        #region GetStyle
        private CellVisualStyle GetStyle(StyleType e)
        {
            CellVisualStyles cvs = _EffectiveStyles;
            if (cvs == null)
                cvs = new CellVisualStyles();
            if (cvs.IsValid(e) == false)
            {
                CellVisualStyle style = new CellVisualStyle();
                StyleType[] css = style.GetApplyStyleTypes(e);
                if (css != null)
                {
                    foreach (StyleType cs in css)
                    {
                        GridColumn.ApplyCellStyle(style, cs);
                        GridRow.ApplyCellStyle(style, cs);
                        style.ApplyStyle(CellStyles[cs]);
                    }
                }
                SuperGrid.DoGetCellStyleEvent(this, e, ref style);
                if (style.Background == null || style.Background.IsEmpty == true)
                    style.Background = new Background(Color.White);
                if (style.Font == null)
                    style.Font = SystemFonts.DefaultFont;
                style.ApplyDefaults();
                cvs[e] = style;
                _EffectiveStyles = cvs;
            }
            return (cvs[e]);
        }
        #endregion
        #region GetSizingStyle
        private CellVisualStyle GetSizingStyle(GridPanel panel)
        {
            StyleType style = panel.GetSizingStyle();
            if (style == StyleType.NotSet)
            {
                style = (IsReadOnly == true)
                    ? StyleType.ReadOnly : StyleType.Default;
            }
            return (GetEffectiveStyle(style));
        }
        #endregion
        #region StyleVisualChangeHandler
        private void StyleVisualChangeHandler(
            INotifyPropertyChanged oldValue, INotifyPropertyChanged newValue)
        {
            //NeedsMeasured = true;
            if (oldValue != null)
                oldValue.PropertyChanged -= StyleChanged;
            if (newValue != null)
                newValue.PropertyChanged += StyleChanged;
        }
        #endregion
        #region StyleChanged
        /// 
        /// Occurs when one of element visual styles has property changes.
        /// Default implementation invalidates visual appearance of element.
        /// 
        /// VisualStyle that changed.
        /// Event arguments.
        protected virtual void StyleChanged(object sender, PropertyChangedEventArgs e)
        {
            ClearEffectiveStyles();
            VisualChangeType changeType = ((VisualPropertyChangedEventArgs)e).ChangeType;
            if (changeType == VisualChangeType.Layout)
            {
                NeedsMeasured = true;
                if (GridColumn != null)
                    GridColumn.NeedsMeasured = true;
                InvalidateLayout();
            }
            else
            {
                InvalidateRender();
            }
        }
        #endregion
        #region ValidateStyle
        private void ValidateStyle()
        {
            if (_StyleUpdateCount != SuperGrid.StyleUpdateCount)
            {
                ClearEffectiveStyles();
                _StyleUpdateCount = SuperGrid.StyleUpdateCount;
            }
        }
        #endregion
        #region InvalidateStyle
        ///
        ///Invalidates the cached Style
        ///definition for all defined StyleTypes
        ///
        public void InvalidateStyle()
        {
            ClearEffectiveStyles();
            InvalidateLayout();
        }
        ///
        ///Invalidate the cached Style
        ///definition for the given StyleType
        ///
        ///
        public void InvalidateStyle(StyleType type)
        {
            if (_EffectiveStyles != null)
            {
                if (_EffectiveStyles[type] != null)
                {
                    _EffectiveStyles[type].Dispose();
                    _EffectiveStyles[type] = null;
                    InvalidateLayout();
                }
            }
        }
        #endregion
        #region ClearEffectiveStyles
        internal void ClearEffectiveStyles()
        {
            if (_EffectiveStyles != null)
            {
                _EffectiveStyles.Dispose();
                _EffectiveStyles = null;
            }
        }
        #endregion
        #endregion
        #region InvalidateRender
        /// 
        /// InvalidateRender
        /// 
        public override void InvalidateRender()
        {
            if (SuperGrid != null && GridColumn != null)
            {
                if (Merged == true)
                {
                    CellRange cr = GetStateCellRange();
                    if (cr != null)
                        InvalidateRender(cr.BackBounds);
                }
                else
                {
                    base.InvalidateRender(BackBounds);
                }
            }
        }
        #endregion
        #region IComparable Members
        /// 
        /// CompareTo
        /// 
        /// 
        /// 
        public int CompareTo(GridCell other)
        {
            int sval = 0;
            if (SuperGrid.DoCompareElementsEvent(GridPanel, this, other, ref sval) == true)
                return (sval);
            if (GridPanel.SortUsingHiddenColumns == false)
            {
                if (Visible == false)
                    return (other.Visible == false ? 0 : -1);
                if (other.Visible == false)
                    return (1);
            }
            object val1 = IsValueExpression ? ExpValue : Value;
            object val2 = other.IsValueExpression ? other.ExpValue : other.Value;
            return (CompareVal.CompareTo(val1, val2));
        }
        #endregion
        #region ToString
        /// 
        /// ToString
        /// 
        /// 
        public override string ToString()
        {
            string s = "GridCell " + ColumnIndex +
                ": {" + (Value ?? "") + "}";
            return (s);
        }
        #endregion
        #region Dispose
        /// 
        /// Dispose
        /// 
        public void Dispose()
        {
            MouseRenderer = null;
            EditControl = null;
            RenderControl = null;
            CellStyles = null;
            ClearEffectiveStyles();
            if (SuperGrid != null)
            {
                if (SuperGrid.ActiveElement == this)
                    SuperGrid.ActiveElement = null;
            }
        }
        #endregion
        #region EditorInfo
        private class EditorInfo
        {
            #region Public variables
            public Type EditorType;
            public Type RenderType;
            public IGridCellEditControl EditControl;
            public IGridCellEditControl RenderControl;
            public object[] EditorParams;
            public object[] RenderParams;
            #endregion
            #region Public properties
            public bool IsEmpty
            {
                get
                {
                    return (EditorType == null && RenderType == null &&
                            (EditorParams == null && RenderParams == null));
                }
            }
            #endregion
        }
        #endregion
        #region CellStates
        [Flags]
        private enum Cs
        {
            AllowEdit = (1 << 0),
            DataError = (1 << 1),
            EmptyCell = (1 << 2),
            ReadOnly = (1 << 3),
            Selected = (1 << 4),
            AnySelected = (1 << 5),
            ValueExpression = (1 << 6),
            MergedTop = (1 << 7),
            MergedLeft = (1 << 8),
            MergedBottom = (1 << 9),
            MergedRight = (1 << 10),
            Merged = (1 << 11),
            Modified = (1 << 12),
        }
        #endregion
    }
    #region CompareVal
    internal class CompareVal
    {
        public static int CompareTo(object val1, object val2)
        {
            if (val1 != null && val1 != DBNull.Value)
            {
                if (val2 != null && val2 != DBNull.Value)
                {
                    if (val1.GetType() == val2.GetType())
                    {
                        IComparable icompa = val1 as IComparable;
                        if (icompa != null)
                            return (icompa.CompareTo(val2));
                    }
                    return (-1);
                }
                return (1);
            }
            if (val2 != null && val2 != DBNull.Value)
                return (-1);
            return (0);
        }
    }
    #endregion
    #region enums
    #region CellArea
    ///
    /// CellArea
    ///
    public enum CellArea
    {
        ///
        /// NoWhere
        ///
        NoWhere,
        ///
        /// InContent
        ///
        InContent,
        ///
        /// InExpandButton
        ///
        InExpandButton,
        ///
        /// InCheckBox
        ///
        InCheckBox,
        ///
        /// InCellInfo
        ///
        InCellInfo,
    }
    #endregion
    #region CellMergeMode
    ///
    /// Specifies the type of merging that is permitted
    /// for cells in the given row or column
    ///
    [Flags]
    public enum CellMergeMode
    {
        ///
        /// Not set
        ///
        NotSet = (0 << 0),
        ///
        /// No merging
        ///
        None = (1 << 0),
        ///
        /// Cells can merge horizontally Left
        ///
        HorizontalLeft = (1 << 1),
        ///
        /// Cells can merge horizontally Right
        ///
        HorizontalRight = (1 << 2),
        ///
        /// Cells can merge horizontally (both left and right)
        ///
        Horizontal = (HorizontalLeft | HorizontalRight),
        ///
        /// Cells can merge vertically
        ///
        Vertical = (1 << 3),
        ///
        /// Cells can merge both horizontally and vertically
        ///
        HorizontalAndVertical = (Horizontal | Vertical),
    }
    ///
    /// Specifies the type of merging that is permitted
    /// for cells in the given row or column
    ///
    public enum CellMergeOrder
    {
        ///
        /// Cells can merge horizontally, then vertically
        ///
        HorizontalThenVertical,
        ///
        /// Cells can merge vertically, then horizontally (this is the default
        /// if CellMergeMode enables both vertical and horizontal merging)
        ///
        VerticalThenHorizontal,
    }
    #endregion
    #region CellSizingSource
    /// 
    /// Specifies the cell value source for the cell
    /// sizing operation (either the actual value, formatted value,
    /// or both)
    /// 
    public enum CellSizingSource
    {
        ActualValue = (1 << 0),      // The actual, unformatted cell value
        FormattedValue = (1 << 1),   // The formatted cell value
        ActualAndFormattedValues = (ActualValue | FormattedValue),  // The actual and formatted cell values
                                                                    // (the maximum width/height of the two is used).
    }
    #endregion
    #endregion
    #region ValueTypeConverter
    ///
    /// ValueTypeConverter
    ///
    public class ValueTypeConverter : TypeConverter
    {
        #region CanConvertTo
        /// 
        /// CanConvertTo
        /// 
        /// 
        /// 
        /// 
        public override bool CanConvertTo(
            ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(string))
                return (true);
            return (base.CanConvertTo(context, destinationType));
        }
        #endregion
        #region ConvertTo
        /// 
        /// ConvertTo
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public override object ConvertTo(
            ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                string s = value as string;
                if (s != null)
                    return (s);
            }
            return (base.ConvertTo(context, culture, value, destinationType));
        }
        #endregion
        #region CanConvertFrom
        /// 
        /// CanConvertFrom
        /// 
        /// 
        /// 
        /// 
        public override bool CanConvertFrom(
            ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return (true);
            return (base.CanConvertFrom(context, sourceType));
        }
        #endregion
        #region ConvertFrom
        /// 
        /// ConvertFrom
        /// 
        /// 
        /// 
        /// 
        /// 
        public override object ConvertFrom(
            ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                GridCell cell = context.Instance as GridCell;
                if (cell != null)
                {
                    Type type = GetEditType(cell);
                    if (type == typeof (GridDoubleInputEditControl))
                        return (ConvertFromToDouble((string)value));
                    if (type == typeof (GridIntegerInputEditControl) ||
                        type == typeof (GridProgressBarXEditControl) ||
                        type == typeof (GridSliderEditControl) ||
                        type == typeof (GridTrackBarEditControl))
                    {
                        return (ConvertFromToInteger((string) value));
                    }
                    if (type == typeof (GridNumericUpDownEditControl))
                        return (ConvertFromToDecimal((string)value));
                    if (type == typeof (GridCheckBoxXEditControl) ||
                        type == typeof (GridCheckBoxEditControl) ||
                        type == typeof(GridSwitchButtonEditControl))
                    {
                        return (ConvertFromToBool((string) value));
                    }
                }
                return (value);
            }
            return base.ConvertFrom(context, culture, value);
        }
        #region ConvertFromToDouble
        private double ConvertFromToDouble(string value)
        {
            try
            {
                return (double.Parse(value));
            }
            catch (Exception)
            {
                throw new ArgumentException("Invalid value to convert to 'double'.");
            }
        }
        #endregion
        #region ConvertFromToInteger
        private int ConvertFromToInteger(string value)
        {
            try
            {
                return (int.Parse(value));
            }
            catch (Exception)
            {
                throw new ArgumentException("Invalid value to convert to 'int'.");
            }
        }
        #endregion
        #region ConvertFromToDecimal
        private decimal ConvertFromToDecimal(string value)
        {
            try
            {
                return (decimal.Parse(value));
            }
            catch (Exception)
            {
                throw new ArgumentException("Invalid value to convert to 'decimal'.");
            }
        }
        #endregion
        #region ConvertFromToBool
        private bool ConvertFromToBool(string value)
        {
            switch (value.ToLower())
            {
                case "y":
                case "yes":
                case "t":
                case "true":
                case "1":
                    return (true);
                case "":
                case "0":
                case "n":
                case "no":
                case "f":
                case "false":
                case null:
                    return (false);
                default:
                    throw new ArgumentException("Invalid value to convert to 'bool'.");
            }
        }
        #endregion
        #endregion
        #region GetEditType
        private Type GetEditType(GridCell cell)
        {
            if (cell.EditorType != null)
                return (cell.EditorType);
            if (cell.GridColumn != null)
                return (cell.GridColumn.EditorType);
            return (null);
        }
        #endregion
    }
    #endregion
}