//------------------------------------------------------------------------------
// <copyright file=”*.cs” company=”EhLib Team”>
//     Copyright (c) 2017 Dmitry V. Bolshakov   
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace EhLib
{
  /// <summary>
  /// Base class for DataGridColumn and DataVertGridRow
  /// </summary>
  [Designer("EhLib.Design.DataGridColumnDesigner" + EhLibUtils.EhLibDesignDesignerVersionInfo)]
  [DesignerCategory("Code")]
  [TypeConverter(typeof(ExpandableObjectConverter))]
  [DesignTimeVisible(false)]
  [ToolboxItem(false)]
  public class PropertyAxisBar : Component/*, IDataCellHolder*/
  {
    #region private consts
    #endregion

    #region privates
    private DataAxisGrid grid;
    private PropertyDescriptor propDescr;
    private string dataPropertyName = string.Empty;
    private string name;
    private int displayIndex = -1;
    private bool visible = true;
    private int visibleIndex = -1;
    private Type dataType;
    private TypeCategory typeCategory;
    private DataValueSource dataValueSource = DataValueSource.DataProperty;

    private Color backColor = Color.Empty;
    private bool backColorStored;

    private DataAxisGridBarTitle title;
    #endregion

    public PropertyAxisBar()
    {
      NewColumn = true;
    }

    #region design-time properties
    [DefaultValue("")]
    //[TypeConverter(typeof(Design.DataAxisGridPropBarDataPropertyNameConverter))]
    //[TypeConverter("EhLib.Design.DataAxisGridPropBarDataPropertyNameConverter, EhLib.WinForms.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d379614f4f89b099")]
    [TypeConverter("EhLib.Design.DataAxisGridPropBarDataPropertyNameConverter")]
    [Category("Data")]
    public string DataPropertyName
    {
      get { return dataPropertyName; }
      set
      {
        if (value == null)
          value = string.Empty;
        if (dataPropertyName != value)
        {
          dataPropertyName = value;
          DataPropertyNameChanged();
        }
      }
    }

    [DefaultValue(DataValueSource.DataProperty)]
    [Category("Data")]
    public DataValueSource DataValueSource
    {
      get
      {
        return dataValueSource;
      }

      set
      {
        if (value != dataValueSource)
        {
          dataValueSource = value;
          Invalidate();
        }
      }
    }

    [DefaultValue(true)]
    public bool Visible
    {
      get
      {
        return visible;
      }
      set
      {
        if (value != visible)
        {
          visible = value;
          if (Grid != null)
          {
            Grid.PropertyAxisBarVisibleChanged(this, value);
          }
        }
      }
    }

    public Color BackColor
    {
      get
      {
        if (backColorStored)
          return backColor;
        else
          return DefaultBackColor();
      }
      set
      {
        if ((backColorStored == false) || (backColor != value))
        {
          backColorStored = true;
          backColor = value;
          BackColorChanged();
        }
      }
    }

    //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    //[Browsable(false)]
    [TypeConverter(typeof(DataGridColumnDataTypeConverter))]
    public Type DataType
    {
      get
      {
        if (dataType != null)
          return dataType;
        else if (DataValueSource == DataValueSource.DataProperty && PropDescr != null)
          return PropDescr.PropertyType;
        else if (DataValueSource == DataValueSource.ListItem && Grid != null)
        {
          Type listItemType = ListBindingHelper.GetListItemType(Grid.CurrencyManager.List);
          return listItemType;
        }
        else
          return null;
      }
      set
      {
        if (dataType != value)
        {
          dataType = value;
          DataTypeChanged();
        }
      }
    }
    #endregion

    #region run-time properties
    //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false)]
    public string Name
    {
      get
      {
        if (Site != null)
          name = Site.Name;
        return name;
      }

      set
      {
        if (string.Equals(this.name, value, StringComparison.Ordinal)) return;

        //if (Site != null)
        //  Site.Name = value;

        this.name = value;

        if (this.Grid != null)
        {
          this.Grid.OnPropBarNameChanged(this);
        }
      }
    }

    [Browsable(false)]
    public DataAxisGrid Grid
    {
      get
      {
        return grid;
      }

      protected internal set
      {
        if (value != grid)
        {
          grid = value;
          GridChanged();
        }
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false)]
    public TypeCategory TypeCategory
    {
      get
      {
        return typeCategory;
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false)]
    public PropertyDescriptor PropDescr
    {
      get { return propDescr; }
      internal set { propDescr = value; }
    }

    [DefaultValue(0)]
    public int MaxLength { get; set; }

    [Browsable(false)]
    public bool AutoGenerated
    {
      get;
      internal set;
    }

    [Browsable(false)]
    public int Index
    {
      get
      {
        //TODO ?
        return -1;

        //if (Grid == null) return -1;
        //for (int i = 0; i < Grid.PropBars.Count; i++)
        //{
        //  if (Grid.PropBars[i] == this)
        //    return i;
        //}
        //return -1;
      }
      //set { ...; }
    }

    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public int DisplayIndex
    {
      get
      {
        return displayIndex;
      }

      set
      {
        if (Grid == null)
          displayIndex = value;
        else
          Grid.SetPropBarDisplayIndex(this, value);
      }
    }

    [Browsable(false)]
    public int VisibleIndex
    {
      get
      {
        return this.visibleIndex;
      }

      internal set
      {
        this.visibleIndex = value;
      }
    }
    #endregion

    #region internal properties
    internal bool NewColumn
    {
      get;
      set;
    }

    [Browsable(false)]
    public bool IsVisible
    {
      get
      {
        if (Grid == null)
          return Visible;
        else
          return Visible && Grid.PropBarCanBeVisible(this);
      }
    }

    //[Browsable(false)]
    //public virtual bool IsReadOnly
    //{
    //  get
    //  {
    //    if (PropDescr != null)
    //      return PropDescr.IsReadOnly;
    //    else
    //      return true;
    //  }
    //}

    protected internal virtual DataAxisGridBarTitle Title
    {
      get
      {
        if (title == null)
          title = CreateDataAxisGridBarTitle();
        return title;
      }
    }

    internal int DisplayIndexInternal
    {
      set
      {
        this.displayIndex = value;
      }
    }
    #endregion

    #region methods
    //BackColor
    public virtual Color DefaultBackColor()
    {
      if (Grid != null)
        return Grid.BackColor;
      else
        return Color.Empty;
    }

    protected virtual void BackColorChanged()
    {
      if (Grid != null)
        Grid.Invalidate();
    }

    protected virtual bool ShouldSerializeBackColor()
    {
      return (backColorStored == true);
    }

    public virtual void ResetBackColor()
    {
      backColorStored = false;
      BackColorChanged();
    }

    //DataType
    //public virtual Type DefaultDataType()
    //{
    //  if (Grid != null)
    //    return Grid.BackColor;
    //  else
    //    return Color.Empty;
    //}

    protected virtual void DataTypeChanged()
    {
      UpdateDefaultPadding();
      UpdateTypeCategory();
      if (Grid != null)
        Grid.UpdatePropBarsList();
    }

    protected virtual bool ShouldSerializeDataType()
    {
      return (dataType != null);
    }

    public virtual void ResetDataType()
    {
      dataType = null;
      DataTypeChanged();
    }


    //PullValue
    protected internal virtual DataAxisGridDataCellPullValueEventArgs CreatePullValueEventArgs(
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cellMan)
    {
      return new DataAxisGridDataCellPullValueEventArgs(propAxisBar, listItemBar, cellMan);
    }

    protected internal virtual void HandlePullValueEvent(DataAxisGridDataCellPullValueEventArgs e)
    {

    }

    protected internal virtual void OnPullValue(DataAxisGridDataCellPullValueEventArgs e)
    {
      throw new InvalidOperationException("PropertyAxisBar.OnPullValue is not implemented");
    }

    //PushValue
    protected internal virtual DataAxisGridDataCellPushValueEventArgs CreatePushValueEventArgs(
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cellMan)
    {
      return new DataAxisGridDataCellPushValueEventArgs(propAxisBar, listItemBar, cellMan);
    }

    protected internal virtual void HandlePushValueEvent(DataAxisGridDataCellPushValueEventArgs e)
    {

    }

    protected internal virtual void OnPushValue(DataAxisGridDataCellPushValueEventArgs e)
    {
      throw new InvalidOperationException("PropertyAxisBar.OnPushValue is not implemented");
    }

    //ParseValue
    protected internal virtual DataAxisGridDataCellParseValueEventArgs CreateParseValueEventArgs(
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cellMan, object inValue)
    {
      return new DataAxisGridDataCellParseValueEventArgs(propAxisBar, listItemBar, cellMan, inValue);
    }

    protected internal virtual void HandleParseValueEvent(DataAxisGridDataCellParseValueEventArgs e)
    {

    }

    protected internal virtual void OnParseValue(DataAxisGridDataCellParseValueEventArgs e)
    {
      object srcValue = e.InValue;
      Type targetType = null;
      Type sourceType = null;
      TypeConverter targetConverter = null;
      TypeConverter sourceConverter = null;
      IFormatProvider formatInfo = null;
      object formattedNullValue = "";
      object dataSourceNullValue;

      if (srcValue == null)
        formattedNullValue = null;
      if (srcValue != null)
        sourceType = srcValue.GetType();
      if (sourceType != null)
        sourceConverter = TypeDescriptor.GetConverter(sourceType);

      if (PropDescr != null)
        targetType = PropDescr.PropertyType;
      if (targetType != null)
        targetConverter = TypeDescriptor.GetConverter(targetType);

      dataSourceNullValue = EhLibManager.DefaultEhLibManager.ValueConverter.GetDefaultDataSourceNullValue(targetType);

      e.OutValue = EhLibManager.DefaultEhLibManager.ValueConverter.ParseValue(srcValue,
        targetType, sourceType, targetConverter, sourceConverter, formatInfo,
        formattedNullValue, dataSourceNullValue);
    }

    //ToolTipInfo
    protected internal virtual DataAxisGridDataCellToolTipInfoEventArgs CreateToolTipInfoEventArgs(
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cellMan)
    {
      return new DataAxisGridDataCellToolTipInfoEventArgs(propAxisBar, listItemBar, cellMan);
    }

    protected internal virtual void HandleToolTipInfoEvent(DataAxisGridDataCellToolTipInfoEventArgs e)
    {
    }

    //DataCellContextMenuStripNeeded
    protected internal virtual DataAxisGridDataCellContextMenuStripNeededEventArgs CreateCellContextMenuStripNeededEventArgs(
      DataAxisGridDataCellMan cellMan, int colIndex, int rowIndex, int areaColIndex, int areaRowIndex, int inCellX, int inCellY,
      Rectangle cellRect, int MousePosX, int MousePosY, PropertyAxisBar propAxisBar, object listItemBar)
    {
      return new DataAxisGridDataCellContextMenuStripNeededEventArgs(cellMan, colIndex, rowIndex, areaColIndex, areaRowIndex, inCellX, inCellY,
        cellRect, MousePosX, MousePosY, propAxisBar, listItemBar);
    }

    protected internal virtual void HandleMouseContextMenuStripNeededEvent(DataAxisGridDataCellContextMenuStripNeededEventArgs e)
    {
    }

    //Other
    protected virtual void GridChanged()
    {
      Title.Grid = Grid;
      //UpdateDefaultPadding();
      //UpdateFooterList();
    }

    protected virtual DataAxisGridBarTitle CreateDataAxisGridBarTitle()
    {
      return new DataAxisGridBarTitle(this);
    }

    protected internal virtual void PerformLayout()
    {
      Title.PerformLayout();
    }

    private void DataPropertyNameChanged()
    {
      if (Grid != null)
        Grid.UpdatePropBarsList();
    }

    public virtual void Invalidate()
    {
    }

    public virtual void UpdateDefaultPadding()
    {
    }

    protected virtual void UpdateTypeCategory()
    {
      typeCategory = EhLibManager.DefaultEhLibManager.GetTypeCategoryForType(DataType);
    }

    protected internal virtual void UpdatedInList()
    {
    }

    public virtual object ParseValue(object listItem, object formattedValue)
    {
      BaseGridCellManager cellMan = GetDataCellMan(listItem);

      DataAxisGridDataCellMan dataCellMan = cellMan as DataAxisGridDataCellMan;
      if (dataCellMan != null)
        return dataCellMan.ProcessParseValue(this, listItem, formattedValue);
      else
        return null;
    }

    protected internal virtual void CellFontChanged()
    {
    }

    public virtual Font DefaultFont()
    {
      return null;
    }

    public virtual Color DefaultForeColor()
    {
      return Color.Empty;
    }

    protected internal virtual void RowHeightAutoExpandChanged()
    {
    }

    public virtual bool HeightOptionsDefaultAutoExpand(GridRowHeightOptions heightOptions)
    {
      return false;
    }

    public virtual int HeightOptionsDefaultContentHeight(GridRowHeightOptions heightOptions)
    {
      return 1;
    }

    public virtual int HeightOptionsDefaultMaxContentHeight(GridRowHeightOptions heightOptions)
    {
      return 0;
    }

    public virtual GridRowHeightUnit HeightOptionsDefaultUnit(GridRowHeightOptions heightOptions)
    {
      return GridRowHeightUnit.TextLine;
    }

    public virtual object GetEmptyValue(object listItem)
    {
      //object result;
      if (listItem != null)
      {
        //object v = listItem;
        if (listItem is DataRowView)
          return DBNull.Value;
        else
          return null;
      }
      else
        return null;
    }

    protected internal virtual void AxisObjectsByDataColRowIndex(int dataColIndex, int dataRowIndex, out PropertyAxisBar propAxisBar, out object listItemBar)
    {
      propAxisBar = null;
      listItemBar = null;
    }

    protected internal virtual bool HandlePaintEvent(DataAxisGridDataCellPaintEventArgs e)
    {
      return false;
    }

    protected internal virtual void HandleDataCellPaintCustomAreaEvent(DataAxisGridDataCellPaintEventArgs e)
    {

    }

    protected internal object GetValue(object listItemBar)
    {
      BaseGridCellManager cellMan = GetDataCellMan(listItemBar);

      DataAxisGridDataCellMan dataCellMan = cellMan as DataAxisGridDataCellMan;
      if (dataCellMan != null)
        return dataCellMan.ProcessPullValue(this, listItemBar);
      else
        return null;
    }

    protected internal void SetValue(object listItemBar, object dataValue)
    {
      BaseGridCellManager cellMan = GetDataCellMan(listItemBar);

      DataAxisGridDataCellMan dataCellMan = cellMan as DataAxisGridDataCellMan;
      if (dataCellMan != null)
        dataCellMan.ProcessPushValue(this, listItemBar, dataValue);
      else
        throw new InvalidOperationException("PropertyAxisBar.SetValue => GetDataCellMan(listItemBar) returned null");
    }

    public virtual BaseGridCellManager GetDataCellMan(object listItemBar)
    {
      return null;
    }

    protected internal virtual DataAxisGridDataCellPaintEventArgs GetDataCellPaintParams(BaseGridCellManager cellManager, Graphics graphics,
        int colIndex, int rowIndex, Rectangle paintRect, BasePaintCellStates state, int areaColIndex, int areaRowIndex,
        Point inCellMousePos, PropertyAxisBar propAxisBar, object listItemBar)
    {
      return new DataAxisGridDataCellPaintEventArgs(cellManager, graphics, colIndex, rowIndex, paintRect, state, areaColIndex, areaRowIndex,
        inCellMousePos, propAxisBar, listItemBar);
    }

    protected internal virtual void PaintCellBackground(DataAxisGridDataCellMan cellMan, DataAxisGridDataCellPaintEventArgs e)
    {
      cellMan.InternalPaintCellBackground(e);
    }

    protected internal virtual void OnGetDataCellBorderParams(BaseGridCellBorderEventArgs e)
    {
    }

    protected internal virtual bool IsPaintEditItemBackground(EditButton editButton, DataAxisGridDataCellPaintEventArgs e, Rectangle itemRect)
    {
      return true;
    }

    protected internal virtual bool IsPaintEditItemForeground(EditButton editButton, DataAxisGridDataCellPaintEventArgs e, Rectangle itemRect)
    {
      return true;
    }

    protected internal virtual void GridCellPosToDataCellPos(int gridColIndex, int gridRowIndex, out int areaColIndex, out int areaRowIndex)
    {
      areaColIndex = gridColIndex;
      areaRowIndex = gridRowIndex;
    }

    protected internal virtual void OnFillFormatParams(DataAxisGridDataCellFormatParamsEventArgs formatParams)
    {
    }

    protected internal virtual DataAxisGridDataCellFormatParamsEventArgs CreateDataCellFormatParamsEventArgs(int colIndex, int rowIndex,
      int areaColIndex, int areaRowIndex, Rectangle cellRect, PropertyAxisBar propAxisBar, object listItemBar,
      DataAxisGridDataCellMan cellMan, DataAxisGridDataCellFormatApplying formatApplying)
    {
      return new DataGridDataCellFormatParamsEventArgs(colIndex, rowIndex, areaColIndex, areaRowIndex, cellRect, propAxisBar, listItemBar,
        cellMan, formatApplying);
    }

    protected internal virtual void DataCellPosToGridCellPos(int areaColIndex, int areaRowIndex, out int gridColIndex, out int gridRowIndex)
    {
      gridColIndex = areaColIndex;
      gridRowIndex = areaRowIndex;
    }

    protected internal virtual BaseGridCellMouseEventArgs CreateDataCellMouseEventArgs(
      int colIndex, int rowIndex, int areaColIndex, int areaRowIndex,
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cell,
      int inCellX, int inCellY, Rectangle cellRect, MouseEventArgs gridMouseArgs)
    {
      return new DataAxisGridDataCellMouseEventArgs(
        cell, colIndex, rowIndex, areaRowIndex, areaColIndex, propAxisBar, listItemBar, inCellX, inCellY, cellRect, gridMouseArgs);
    }

    protected internal virtual DataAxisGridDataCellEventArgs CreateDataCellEventArgs(
      int colIndex, int rowIndex, int areaColIndex, int areaRowIndex, Rectangle cellRect,
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cell
      )
    {
      return new DataAxisGridDataCellEventArgs(colIndex, rowIndex, areaColIndex, areaRowIndex, cellRect, propAxisBar, listItemBar, cell);
    }

    protected internal virtual DataAxisGridDataCellEnterEventArgs CreateDataCellEnterEventArgs(
      int colIndex, int rowIndex, int areaColIndex, int areaRowIndex, Rectangle cellRect, int leaveColIndex, int leaveRowIndex,
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cell)
    {
      return new DataAxisGridDataCellEnterEventArgs(colIndex, rowIndex, areaColIndex, areaRowIndex, cellRect, leaveColIndex, leaveRowIndex, propAxisBar, listItemBar, cell);
    }

    protected internal virtual void OnDataCellClientAreaNeeded(DataAxisGridDataCellClientAreaNeededEventArgs e)
    {
      Grid.HandleDataCellClientAreaNeededEvent(e);
      HandleDataCellClientAreaNeededEvent(e);
    }

    protected virtual void HandleDataCellClientAreaNeededEvent(DataAxisGridDataCellClientAreaNeededEventArgs e)
    {
    }

    protected internal virtual DataAxisGridDataCellClientAreaNeededEventArgs CreateDataCellClientAreaNeededEventArgs(PropertyAxisBar propAxisBar,
        object listItemBar, Rectangle cellRect, DataAxisGridDataCellMan cellMan)
    {
      return new DataAxisGridDataCellClientAreaNeededEventArgs(propAxisBar, listItemBar, cellRect, cellMan);
    }

    protected internal virtual DataAxisGridDataCellLeaveEventArgs CreateDataCellLeaveEventArgs(
      int colIndex, int rowIndex, int areaColIndex, int areaRowIndex, Rectangle cellRect, int enterColIndex, int enterRowIndex,
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cell)
    {
      return new DataAxisGridDataCellLeaveEventArgs(colIndex, rowIndex, areaColIndex, areaRowIndex, cellRect, enterColIndex, enterRowIndex, propAxisBar, listItemBar, cell);
    }

    protected internal virtual void OnDataCellContentClick(DataAxisGridDataCellEventArgs e)
    {
    }

    protected internal virtual bool IsDataCellSelected(int dataColIndex, int dataRowIndex)
    {
      return false;
    }

    protected internal virtual void HandleMouseDownEvent(BaseGridCellMouseEventArgs e)
    {
    }

    protected internal virtual void HandleMouseMoveEvent(BaseGridCellMouseEventArgs e)
    {
    }

    protected internal virtual void HandleMouseUpEvent(BaseGridCellMouseEventArgs e)
    {
    }

    protected internal virtual void HandleMouseClickEvent(BaseGridCellMouseEventArgs e)
    {
    }

    protected internal virtual void HandleMouseDoubleClickEvent(BaseGridCellMouseEventArgs e)
    {
    }

    protected internal virtual void HandleMouseEnterEvent(BaseGridCellEnterEventArgs e)
    {
    }

    protected internal virtual void HandleMouseLeaveEvent(BaseGridCellLeaveEventArgs e)
    {
    }

    protected internal virtual void HandleMouseHoverEvent(BaseGridCellMouseEventArgs e)
    {
    }

    //protected internal virtual BaseGridCellCustomAreaMeasuresEventArgs CreateCellCustomAreaMeasuresEventArgs(
    //  int colIndex, int rowIndex, int areaColIndex, int areaRowIndex, PropertyAxisBar propAxisBar, object listItemBar, 
    //  CellCustomAreaMeasures areaMeasures)
    //{
    //  return new BaseGridCellCustomAreaMeasuresEventArgs(colIndex, rowIndex, areaColIndex, areaRowIndex, areaMeasures);
    //}

    //protected internal virtual void OnCellCustomAreaMeasuresNeeded(BaseGridCellCustomAreaMeasuresEventArgs e)
    //{
    //}

    protected internal virtual DataAxisGridDataCellOptimalWidthNeededEventArgs CreateDataCellOptimalWidthNeededEventArgs(
      PropertyAxisBar propAxisBar, object listItemBar, DataAxisGridDataCellMan cellMan)
    {
      return new DataAxisGridDataCellOptimalWidthNeededEventArgs(propAxisBar, listItemBar, cellMan);
    }

    protected internal virtual void HandleCellOptimalWidthNeededEvent(DataAxisGridDataCellOptimalWidthNeededEventArgs e)
    {
    }

    #endregion
  }

  [TypeConverter(typeof(ExpandableObjectConverter))]
  [DesignerCategory("Code")]
  [ToolboxItem(false)]
  public class DataAxisGridBarTitle : Component, ICellBackFillerOwner, ICellImageBoxOwner
  {
    #region privates
    private DataAxisGrid grid;
    private readonly PropertyAxisBar propBar;

    private string text = string.Empty;
    private bool textStored;
    private Font font;
    private Color foreColor = Color.Empty;
    private bool foreColorStored;
    private bool endEllipsis;
    private bool endEllipsisStored;

    private HorizontalAlignment horzAlign;
    private bool horzAlignStored;
    private Padding padding = new Padding(0);
    private bool paddingStored;
    private readonly Padding defaultPadding = new Padding(3, 2, 3, 4);
    private VerticalAlignment vertAlign;
    private bool vertAlignStored;
    private string toolTipText;
    private readonly CellBackFiller backFiller;
    private readonly CellImageBox imageBox;
    #endregion

    public DataAxisGridBarTitle(PropertyAxisBar propBar)
    {
      this.propBar = propBar;
      backFiller = new CellBackFiller(this);
      imageBox = new CellImageBox(this);
    }

    #region design-time properties
    [DefaultValue("")]
    public string Text
    {
      get
      {
        if (textStored)
          return text;
        else
          return DefaultText();
      }
      set
      {
        if ((textStored == false) || (text != value))
        {
          textStored = true;
          text = value;
          if (text == null)
            text = string.Empty;
          CaptionChanged();
        }
      }
    }

    public Font Font
    {
      get
      {
        if (font != null)
          return font;
        else
          return DefaultFont();
      }
      set
      {
        font = value;
        FontChanged();
      }
    }

    public Color ForeColor
    {
      get
      {
        if (foreColorStored)
          return foreColor;
        else
          return DefaultForeColor();
      }
      set
      {
        if ((foreColorStored == false) || (foreColor != value))
        {
          foreColorStored = true;
          foreColor = value;
          ForeColorChanged();
        }
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public CellBackFiller BackFiller
    {
      get
      {
        return backFiller;
      }
    }

    public Padding Padding
    {
      get
      {
        if (paddingStored)
          return padding;
        else
          return DefaultPadding();
      }
      set
      {
        padding = value;
        paddingStored = true;
        PaddingChanged();
      }
    }

    public HorizontalAlignment HorzAlign
    {
      get
      {
        if (horzAlignStored)
          return horzAlign;
        else
          return DefaultHorzAlign();
      }
      set
      {
        if ((horzAlignStored == false) || (horzAlign != value))
        {
          horzAlignStored = true;
          horzAlign = value;
          TextAlignChanged();
        }
      }
    }

    public VerticalAlignment VertAlign
    {
      get
      {
        if (vertAlignStored)
          return vertAlign;
        else
          return DefaultVertAlign();
      }
      set
      {
        if ((vertAlignStored == false) || (vertAlign != value))
        {
          vertAlignStored = true;
          vertAlign = value;
          TextAlignChanged();
        }
      }
    }

    public bool EndEllipsis
    {
      get
      {
        if (endEllipsisStored)
          return endEllipsis;
        else
          return DefaultEndEllipsis();
      }
      set
      {
        if ((endEllipsisStored == false) || (endEllipsis != value))
        {
          endEllipsisStored = true;
          endEllipsis = value;
          EndEllipsisChanged();
        }
      }
    }

    [DefaultValue("")]
    [Localizable(true)]
    public string ToolTipText
    {
      get
      {
        return toolTipText;
      }
      set
      {
        if (value != toolTipText)
        {
          toolTipText = value;
          ToolTipTextChanged();
        }
      }
    }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public CellImageBox ImageBox
    {
      get
      {
        return imageBox;
      }
    }
    #endregion

    #region public properties
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [Browsable(false)]
    protected PropertyAxisBar PropBar
    {
      get { return propBar; }
    }

    [Browsable(false)]
    protected internal virtual DataAxisGrid Grid
    {
      get
      {
        return grid;
      }

      set
      {
        if (value != grid)
        {
          grid = value;
          //titleCell.Grid = grid;
        }
      }
    }
    #endregion

    #region methods
    //ICellBackFillerOwner
    void ICellBackFillerOwner.BackFillerChanged(CellBackFiller backFiller)
    {
      if (Grid != null)
        Grid.Invalidate();
    }

    Color ICellBackFillerOwner.BackFillerDefaultColor(CellBackFiller backFiller)
    {
      return Grid.TitleBar.BackFiller.Color;
    }

    Color ICellBackFillerOwner.BackFillerDefaultSecondColor(CellBackFiller backFiller)
    {
      return Grid.TitleBar.BackFiller.SecondColor;
    }

    CellFillStyle ICellBackFillerOwner.BackFillerDefaultFillStyle(CellBackFiller backFiller)
    {
      return Grid.TitleBar.BackFiller.FillStyle;
    }

    CellInnerBorderStyle ICellBackFillerOwner.BackFillerDefaultInnerBorder(CellBackFiller backFiller)
    {
      return Grid.TitleBar.BackFiller.InnerBorder;
    }

    //Other
    public virtual string DefaultText()
    {
      return PropBar.DataPropertyName;
    }

    public virtual Color DefaultForeColor()
    {
      if (PropBar.Grid != null)
        return PropBar.Grid.TitleBar.ForeColor;
      else
        return Color.Empty;
    }

    public virtual void ResetCaption()
    {
      textStored = false;
      CaptionChanged();
    }

    public virtual void ResetEndEllipsis()
    {
      endEllipsisStored = false;
      EndEllipsisChanged();
    }

    public virtual void ResetFont()
    {
      font = null;
      FontChanged();
    }

    public virtual void ResetForeColor()
    {
      foreColorStored = false;
      ForeColorChanged();
    }

    //public virtual void ResetHeightAutoExpand()
    //{
    //  heightAutoExpandStored = false;
    //  HeightAutoExpandChanged();
    //}

    public void ResetHorzAlign()
    {
      horzAlignStored = false;
      TextAlignChanged();
    }

    public virtual void ResetPadding()
    {
      paddingStored = false;
      PaddingChanged();
    }

    public void ResetVertAlign()
    {
      vertAlignStored = false;
      TextAlignChanged();
    }

    protected virtual void CaptionChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.UpdatePropBarsList();
    }

    protected virtual bool DefaultEndEllipsis()
    {
      if (PropBar.Grid != null)
        return PropBar.Grid.TitleBar.EndEllipsis;
      else
        return false;
    }

    protected virtual Padding DefaultPadding()
    {
      if (PropBar.Grid != null)
        return PropBar.Grid.TitleBar.Padding;
      else
        return defaultPadding;
    }

    protected virtual void EndEllipsisChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.InvalidateGrid();
    }

    protected virtual void ForeColorChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.InvalidateGrid();
    }

    protected virtual void PaddingChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.UpdateBaseFixedBands();
    }

    protected virtual bool ShouldSerializeCaption()
    {
      return (textStored == true);
    }

    protected virtual bool ShouldSerializeEndEllipsis()
    {
      return (endEllipsisStored == true);
    }

    protected virtual bool ShouldSerializeFont()
    {
      return (font != null);
    }

    protected virtual bool ShouldSerializeForeColor()
    {
      return (foreColorStored == true);
    }

    //protected virtual bool ShouldSerializeHeightAutoExpand()
    //{
    //  return (heightAutoExpandStored == true);
    //}

    protected virtual bool ShouldSerializeHorzAlign()
    {
      return (horzAlignStored == true);
    }

    protected virtual bool ShouldSerializePadding()
    {
      return (paddingStored == true);
    }

    protected virtual bool ShouldSerializeVertAlign()
    {
      return (vertAlignStored == true);
    }

    protected virtual void TextAlignChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.InvalidateGrid();
    }

    protected virtual void TextOrientationChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.UpdatePropBarsList();
    }

    private Font DefaultFont()
    {
      if (PropBar.Grid != null)
        return PropBar.Grid.TitleBar.Font;
      else
        return null;
    }

    private HorizontalAlignment DefaultHorzAlign()
    {
      return PropBar.Grid.TitleBar.HorzAlign;
    }

    private VerticalAlignment DefaultVertAlign()
    {
      return PropBar.Grid.TitleBar.VertAlign;
    }

    private void FontChanged()
    {
      if (PropBar.Grid != null)
        PropBar.Grid.UpdateBaseFixedBands();
    }

    protected internal virtual void PerformLayout()
    {
      //TitleCell.PerformLayout(this);
    }

    protected internal virtual void UpdateMetrics(Size cellSize)
    {
    }

    protected virtual void ToolTipTextChanged()
    {
    }

    void ICellImageBoxOwner.CellImageBoxChanged(CellImageBox imageBox)
    {
      if (PropBar.Grid != null)
        PropBar.Grid.UpdateBaseFixedBands();
    }
    #endregion Methods

  }

  public class ListItemAxisBar
  {
  }

  public class DataGridColumnDataTypeConverter : TypeConverter
  {
    private static Type[] types = new Type[] {
            typeof(Boolean),
            typeof(Byte),
            typeof(Byte[]),
            typeof(Char),
            typeof(DateTime),
            typeof(Decimal),
            typeof(Double),
            typeof(Guid),
            typeof(Int16),
            typeof(Int32),
            typeof(Int64),
            typeof(object),
            typeof(SByte),
            typeof(Single),
            typeof(string),
            typeof(TimeSpan),
            typeof(UInt16),
            typeof(UInt32),
            typeof(UInt64),
            typeof(SqlInt16),
            typeof(SqlInt32),
            typeof(SqlInt64),
            typeof(SqlDecimal),
            typeof(SqlSingle),
            typeof(SqlDouble),
            typeof(SqlString),
            typeof(SqlBoolean),
            typeof(SqlBinary),
            typeof(SqlByte),
            typeof(SqlDateTime),
            typeof(SqlGuid),
            typeof(SqlMoney),
            typeof(SqlBytes),
            typeof(SqlChars),
            typeof(SqlXml)
        };
    private StandardValuesCollection values;

    public DataGridColumnDataTypeConverter()
    {
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
      if (destinationType == typeof(InstanceDescriptor))
      {
        return true;
      }
      return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
      if (destinationType == null)
      {
        throw new ArgumentNullException("destinationType");
      }

      if (destinationType == typeof(string))
      {
        if (value == null)
        {
          return String.Empty;
        }
        else
        {
          value.ToString();
        }
      }
      if (value != null && destinationType == typeof(InstanceDescriptor))
      {
        Object newValue = value;
        if (value is string)
        {
          for (int i = 0; i < types.Length; i++)
          {
            if (types[i].ToString().Equals(value))
              newValue = types[i];
          }
        }

        if (value is Type || value is string)
        {
          System.Reflection.MethodInfo method = typeof(Type).GetMethod("GetType", new Type[] { typeof(string) }); // change done for security review 
          if (method != null)
          {
            return new InstanceDescriptor(method, new object[] { ((Type)newValue).AssemblyQualifiedName });
          }
        }
      }

      return base.ConvertTo(context, culture, value, destinationType);
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
      if (sourceType == typeof(string))
      {
        return true;
      }
      return base.CanConvertTo(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
      if (value != null && value.GetType() == typeof(string))
      {
        for (int i = 0; i < types.Length; i++)
        {
          if (types[i].ToString().Equals(value))
            return types[i];
        }

        return typeof(string);
      }

      return base.ConvertFrom(context, culture, value);
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
      if (values == null)
      {
        object[] objTypes;

        if (types != null)
        {
          objTypes = new object[types.Length];
          Array.Copy(types, objTypes, types.Length);
        }
        else
        {
          objTypes = null;
        }

        values = new StandardValuesCollection(objTypes);
      }
      return values;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
      return true;
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
      return true;
    }
  }

}
