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

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using EhLib.Windows.Forms.VisualStyles;

namespace EhLib
{

  public class BaseGridFillFixedCellEventArgs : EventArgs
  {

    public BaseGridFillFixedCellEventArgs()
    {
    }

    public Rectangle CellRect { get; set; }
    public Graphics Graphics { get; set; }
    public bool IsHot { get; set; }
    public bool IsPressed { get; set; }
    public bool IsSelected { get; set; }
    public Color BackColor { get; set; }
    public CellFillStyle FillStyle { get; set; }
    public CellInnerBorderStyle InnerBorder { get; set; }
    public Color FillColor { get; set; }
    public Color SecondFillColor { get; set; }
  }

  public class SortMarkerPaintEventArgs : EventArgs
  {

    public SortMarkerPaintEventArgs()
    {
    }

    public Graphics Graphics { get; set; }
    public Rectangle MarkerAreaRect { get; set; }
    public Color ControlBackColor { get; set; }
    public Color ControlForeColor { get; set; }
    public SortMarkerStyle SortMarkerStyle { get; set; }
    public SortOrder SortOrder { get; set; }
    public int SortIndex { get; set; }
    public Color SortMarkerColor { get; set; }

  }

  public class InTitleFilterButtonMetrics
  {
    //public Size Size { get; set; }
    public Rectangle ButtonRect { get; set; }
    public Padding Margin { get; set; }
  }

  public class InTitleFilterButtonArgs
  {
    private readonly Graphics graphics;
    private readonly Rectangle rect;
    private readonly PushButtonState state;
    private readonly bool filterHaveData;
    private readonly bool paintBack;

    public InTitleFilterButtonArgs(Graphics graphics, Rectangle rect, PushButtonState state, bool filterHaveData, bool paintBack)
    {
      this.graphics = graphics;
      this.rect = rect;
      this.state = state;
      this.filterHaveData = filterHaveData;
      this.paintBack = paintBack;
    }

    public Graphics Graphics
    {
      get { return graphics; }
    }

    public Rectangle Rect
    {
      get { return rect; }
    }

    public PushButtonState State
    {
      get { return state; }
    }

    public bool FilterHaveData
    {
      get { return filterHaveData; }
    }

    public bool PaintBack
    {
      get { return paintBack; }
    }
  }

  public enum PushButtonBorderStyle
    { Thin, Thick };

  public class PushButtonBackDrawArgs
  {
    private readonly Graphics graphics;
    private readonly Rectangle rect;
    private readonly PushButtonState state;
    private readonly bool parentHasFrame;
    private readonly PushButtonBorderStyle borderStyle;

    public PushButtonBackDrawArgs(Graphics graphics, Rectangle rect, PushButtonState state, bool parentHasFrame, PushButtonBorderStyle borderStyle)
    {
      this.graphics = graphics;
      this.rect = rect;
      this.state = state;
      this.parentHasFrame = parentHasFrame;
      this.borderStyle = borderStyle;
    }

    public Graphics Graphics
    {
      get { return graphics; }
    }

    public Rectangle Rect
    {
      get { return rect; }
    }

    public PushButtonState State
    {
      get { return state; }
    }

    public bool ParentHasFrame
    {
      get { return parentHasFrame; }
    }

    public PushButtonBorderStyle BorderStyle
    {
      get { return borderStyle; }
    }
  }

  public sealed class EhLibDrawStyle
  {
    #region fields
    private static DataGridDrawStyle _defDataGridDrawStyle;
    private static BaseGridDrawStyle _defBaseGridDrawStyle;
    private static TextBoxDrawStyle _defTextBoxDrawStyle;
    private static ToolElementsDrawStyle _defToolElementsDrawStyle;
    private static ProgressBarDrawStyle _defProgressBarDrawStyle;
    private static DataVertGridDrawStyle _defDataVertGridDrawStyle;
    private static BaseElementsDrawStyle _defBaseElementsDrawStyle;
    #endregion fields

    private EhLibDrawStyle()
    {
    }

    #region properties
    public static DataGridDrawStyle DefaultDataGridDrawStyle
    {
      get
      {
        if (_defDataGridDrawStyle == null)
          _defDataGridDrawStyle = new DataGridDrawStyle();
        return _defDataGridDrawStyle;
      }
      set
      {
        _defDataGridDrawStyle = value;
      }
    }

    public static DataVertGridDrawStyle DefaultDataVertGridDrawStyle
    {
      get
      {
        if (_defDataVertGridDrawStyle == null)
          _defDataVertGridDrawStyle = new DataVertGridDrawStyle();
        return _defDataVertGridDrawStyle;
      }
      set
      {
        _defDataVertGridDrawStyle = value;
      }
    }

    public static BaseGridDrawStyle DefaultBaseGridDrawStyle
    {
      get
      {
        if (_defBaseGridDrawStyle == null)
          _defBaseGridDrawStyle = new BaseGridDrawStyle();
        return _defBaseGridDrawStyle;
      }
      set
      {
        _defBaseGridDrawStyle = value;
      }
    }

    public static TextBoxDrawStyle DefaultTextBoxDrawStyle
    {
      get
      {
        if (_defTextBoxDrawStyle == null)
          _defTextBoxDrawStyle = new TextBoxDrawStyle();
        return _defTextBoxDrawStyle;
      }
      set
      {
        _defTextBoxDrawStyle = value;
      }
    }

    public static ToolElementsDrawStyle DefaultToolElementsDrawStyle
    {
      get
      {
        if (_defToolElementsDrawStyle == null)
          _defToolElementsDrawStyle = new ToolElementsDrawStyle();
        return _defToolElementsDrawStyle;
      }
      set
      {
        _defToolElementsDrawStyle = value;
      }
    }

    public static ProgressBarDrawStyle DefaultProgressBarDrawStyle
    {
      get
      {
        if (_defProgressBarDrawStyle == null)
          _defProgressBarDrawStyle = new ProgressBarDrawStyle();
        return _defProgressBarDrawStyle;
      }
      set
      {
        _defProgressBarDrawStyle = value;
      }
    }

    public static BaseElementsDrawStyle DefaultBaseElementsDrawStyle
    {
      get
      {
        if (_defBaseElementsDrawStyle == null)
          _defBaseElementsDrawStyle = new BaseElementsDrawStyle();
        return _defBaseElementsDrawStyle;
      }
      set
      {
        _defBaseElementsDrawStyle = value;
      }
    }
    #endregion properties
  }

  public class BaseElementsDrawStyle
  {
    public virtual void DrawCheckBox(Graphics g, Point location, CheckBoxState state, bool flat, bool tryUseVisualStyles)
    {
      if ((!flat) || 
          (tryUseVisualStyles && Application.RenderWithVisualStyles))
      {
        CheckBoxRenderer.DrawCheckBox(g, location, state);
      }
      else
      {
        Size chbSize = CheckBoxRenderer.GetGlyphSize(g, state);
        Rectangle fullRect = new Rectangle(location, chbSize);
        Rectangle chbRect = fullRect;
        chbRect.Inflate(-2, -2);

        Region oldClip = g.Clip;
        g.SetClip(chbRect, CombineMode.Intersect);

        CheckBoxRenderer.DrawCheckBox(g, location, state);

        if (oldClip != null)
          g.Clip = oldClip;

        chbRect = EhLibUtils.ChangeRectangle(chbRect, -1, -1, 1, 1);
        g.DrawRectangle(SystemPens.ControlDark, chbRect);
        //ControlPaint.DrawVisualStyleBorder(g, chbRect);
      }
    }
  }

  public class DataGridDrawStyle : BaseGridDrawStyle, IDisposable
  {
    Font sortMarkerFont;
    Cursor downArrowSelectCursor;
    Cursor rightArrowSelectCursor;
    readonly Padding columnOptionsSidePadding = new Padding(3, 2, 3, 2);
    private bool disposed;

    public DataGridDrawStyle()
    {
    }

    ~DataGridDrawStyle()
    {
      Dispose(false);
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (disposed)
        return;
      if (disposing)
      {
        if (sortMarkerFont != null) sortMarkerFont.Dispose();
        if (downArrowSelectCursor != null) downArrowSelectCursor.Dispose();
        if (rightArrowSelectCursor != null) rightArrowSelectCursor.Dispose();
      }
      disposed = true;
    }

    public Font SortMarkerFont
    {
      get
      {
        if (sortMarkerFont == null)
          sortMarkerFont = new Font("Arial", 6F, FontStyle.Regular, GraphicsUnit.Point, 204);
        return sortMarkerFont;
      }
    }

    public virtual bool FixFillFixedCellRect(DataGridEh dataGrid, BaseGridFillFixedCellEventArgs e, ref Rectangle fillRect)
    {
      if (Application.RenderWithVisualStyles)
      {
        fillRect.Width = fillRect.Width + 2;
        fillRect.Height = fillRect.Height + 2;
        return true;
      }
      else
      {
        return false;
      }
    }

    public virtual void FillIndicatorCell(DataGridEh dataGrid, BaseGridFillFixedCellEventArgs e)
    {
      FillFixedCell(dataGrid, e);
    }

    public virtual void FillTopIndicatorCell(DataGridEh dataGrid, BaseGridFillFixedCellEventArgs e)
    {
      FillFixedCell(dataGrid, e);
    }

    public virtual void FillTitleCell(DataGridEh dataGrid, BaseGridFillFixedCellEventArgs e)
    {
      FillFixedCell(dataGrid, e);
    }

    public virtual void FillFixedCell(DataGridEh dataGrid, BaseGridFillFixedCellEventArgs e)
    {
      base.FillFixedCell(dataGrid, e);
    }

    public virtual Size GetSortMarkerSize(SortMarkerStyle sortMarkerStyle)
    {
      if (sortMarkerStyle == SortMarkerStyle.Default)
        sortMarkerStyle = GetDefaultSortMarkerStyle();
      if (sortMarkerStyle == SortMarkerStyle.Themed && !Application.RenderWithVisualStyles)
        sortMarkerStyle = SortMarkerStyle.Solid;
      switch (sortMarkerStyle)
      {
        case SortMarkerStyle.Framed:
          {
            return new Size(7, 8);
          }
        case SortMarkerStyle.Solid:
          {
            return new Size(9, 5);
          }
        case SortMarkerStyle.Themed:
          {
            VisualStyleElement element = VisualStyleElement.Header.SortArrow.SortedUp;
            VisualStyleRenderer render = new VisualStyleRenderer(element);
            Size sz = render.GetPartSize(EhLibUtils.DisplayGraphicsCash, ThemeSizeType.Draw);
            return sz;
          }
      }
      return new Size(0, 0);
    }

    public virtual SortMarkerStyle GetDefaultSortMarkerStyle()
    {
      if (Application.RenderWithVisualStyles)
        return SortMarkerStyle.Themed;
      else
        return SortMarkerStyle.Framed;
    }

    public virtual Size GetSortMarkerAreaSize(SortMarkerStyle sortMarkerStyle)
    {
      Size result = GetSortMarkerSize(sortMarkerStyle);
      Size textSize = EhLibUtils.DisplayGraphicsCash.MeasureString("0", SortMarkerFont).ToSize();
      result.Width = result.Width + textSize.Width;
      if (textSize.Height > result.Height)
        result.Height = textSize.Height;
      return result;
    }

    public virtual void DrawSortMarkerArea(SortMarkerPaintEventArgs e)
    {
      Size sz = GetSortMarkerSize(e.SortMarkerStyle);
      Rectangle elemRect = e.MarkerAreaRect;

      elemRect.Width = sz.Width;

      DrawSortMarker(ref elemRect, e);

      if (e.SortIndex >= 1)
      {
        elemRect.X = elemRect.X + elemRect.Width;
        elemRect.Width = e.MarkerAreaRect.Width - elemRect.Width;
        DrawSortIndex(ref elemRect, e);
      }
    }

    public virtual void DrawSortMarker(ref Rectangle sortMarkerRect, SortMarkerPaintEventArgs e)
    {

      SortMarkerStyle sortMarkerStyle = e.SortMarkerStyle;
      if (sortMarkerStyle == SortMarkerStyle.Default)
        sortMarkerStyle = GetDefaultSortMarkerStyle();

      switch (sortMarkerStyle)
      {
        case SortMarkerStyle.Framed:
          {
            DrawFramedSortMarker(ref sortMarkerRect, e);
            return;
          }
        case SortMarkerStyle.Solid:
          {
            DrawSolidSortMarker(ref sortMarkerRect, e);
            return;
          }
        case SortMarkerStyle.Themed:
          {
            DrawThemedSortMarker(ref sortMarkerRect, e);
            return;
          }
      }
    }

    public virtual void DrawThemedSortMarker(ref Rectangle sortMarkerRect, SortMarkerPaintEventArgs e)
    {
      if (Application.RenderWithVisualStyles)
      {
        VisualStyleElement element;
        VisualStyleRenderer render;

        if (e.SortOrder == SortOrder.Ascending)
          element = VisualStyleElement.Header.SortArrow.SortedUp;
        else
          element = VisualStyleElement.Header.SortArrow.SortedDown;
        render = new VisualStyleRenderer(element);

        render.DrawBackground(e.Graphics, sortMarkerRect);
      }
      else
      {
        DrawSolidSortMarker(ref sortMarkerRect, e);
      }
    }

    public virtual void DrawSolidSortMarker(ref Rectangle sortMarkerRect, SortMarkerPaintEventArgs e)
    {
      Rectangle smRect = new Rectangle();

      smRect.Size = GetSortMarkerSize(e.SortMarkerStyle);
      smRect = EhLibUtils.RectCenter(smRect, sortMarkerRect);

      if (e.SortOrder == SortOrder.Ascending)
        EhLibUtils.FillGradient(e.Graphics, smRect.Location, new Point[]
          { new Point(0, 0), new Point(9, 0),
           new Point(1, 1), new Point(8, 1),
           new Point(2, 2), new Point(7, 2),
           new Point(3, 3), new Point(6, 3),
           new Point(4, 4), new Point(5, 4)
          },
          e.SortMarkerColor, e.SortMarkerColor);
      else
        EhLibUtils.FillGradient(e.Graphics, smRect.Location, new Point[]
          { new Point(0, 4), new Point(9, 4),
            new Point(1, 3), new Point(8, 3),
            new Point(2, 2), new Point(7, 2),
            new Point(3, 1), new Point(6, 1),
            new Point(4, 0), new Point(5, 0)
          },
          e.SortMarkerColor, e.ControlForeColor);
    }

    public virtual void DrawFramedSortMarker(ref Rectangle sortMarkerRect, SortMarkerPaintEventArgs e)
    {
      Point[] points = new Point[4];
      Pen blackPen = new Pen(e.SortMarkerColor, 1);
      Rectangle smRect = new Rectangle();

      smRect.Size = GetSortMarkerSize(e.SortMarkerStyle);
      smRect = EhLibUtils.RectCenter(smRect, sortMarkerRect);

      if (e.SortOrder == SortOrder.Ascending)
      {
        points[0].X = (smRect.Right + smRect.Left) / 2;
        points[0].Y = smRect.Bottom;
        points[1].X = smRect.Left;
        points[1].Y = smRect.Top + 1;
        points[2].X = smRect.Right - 1;
        points[2].Y = smRect.Top + 1;
        points[3].X = (smRect.Right + smRect.Left) / 2;
        points[3].Y = smRect.Bottom;
      }
      else
      {
        points[0].X = (smRect.Right + smRect.Left) / 2;
        points[0].Y = smRect.Top;
        points[1].X = smRect.Right - 1;
        points[1].Y = smRect.Bottom - 1;
        points[2].X = smRect.Left;
        points[2].Y = smRect.Bottom - 1;
        points[3].X = (smRect.Right + smRect.Left) / 2;
        points[3].Y = smRect.Top;
      }

      e.Graphics.DrawPolygon(blackPen, points);
    }

    public virtual void DrawSortIndex(ref Rectangle sortIndexRect, SortMarkerPaintEventArgs e)
    {
      string smIndexStr = e.SortIndex.ToString();
      Font font = SortMarkerFont;
      TextFormatFlags fmtFlags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;

      TextRenderer.DrawText(e.Graphics, smIndexStr, font, sortIndexRect, e.ControlForeColor, fmtFlags);
    }

    public virtual Cursor DownArrowSelectCursor()
    {
      if (downArrowSelectCursor == null)
      {
        using (MemoryStream ms = new MemoryStream(Properties.Resources.DownArrowSelectCur))
        {
          downArrowSelectCursor = new Cursor(ms);
        }
      }
      return downArrowSelectCursor;
    }

    public virtual Cursor RightArrowSelectCursor()
    {
      if (rightArrowSelectCursor == null)
      {
        using (MemoryStream ms = new MemoryStream(Properties.Resources.RightArrowSelectCur))
        {
          rightArrowSelectCursor = new Cursor(ms);
        }
      }
      return rightArrowSelectCursor;
    }

    public virtual int ColSelectionAreaHeight()
    {
      return 20;
    }

    public virtual Padding GetColumnOptionsSidePadding()
    {
      return columnOptionsSidePadding;
    }

    //public virtual Color GetFixedSelectedBackColor(DataGridEh dataGrid, Color backColor)
    //{

    //}

    public virtual Color GetFixedSelectedForeColor(DataGridEh dataGrid, Color backColor, Color foreColor)
    {
      if (Application.RenderWithVisualStyles)
      {
        return foreColor;
      }
      else
      {
        return SystemColors.HighlightText;
      }
    }

    public virtual void GetInTitleFilterButtonMetrics(DataGridEh dataGrid, Size cellSize, InTitleFilterButtonMetrics metric)
    {
      Size buttonSize = new Size(SystemInformation.VerticalScrollBarWidth, SystemInformation.VerticalScrollBarWidth);

      buttonSize.Width = buttonSize.Width * 9 / 10;

      metric.Margin = new Padding(1);

      if (buttonSize.Width + metric.Margin.Left + metric.Margin.Right > cellSize.Width / 2)
        buttonSize.Width = cellSize.Width / 2 - metric.Margin.Left - metric.Margin.Right;

      buttonSize.Height = buttonSize.Width * 3 / 2;
      if (buttonSize.Height + metric.Margin.Top + metric.Margin.Bottom > cellSize.Height)
        buttonSize.Height = cellSize.Height - metric.Margin.Top - metric.Margin.Bottom;

      Size buttonAreaSize = buttonSize;
      buttonAreaSize.Height += metric.Margin.Top + metric.Margin.Bottom;
      buttonAreaSize.Width += metric.Margin.Left + metric.Margin.Right;

      Rectangle filterButtonRect = new Rectangle(
        cellSize.Width - buttonSize.Width,
        0,
        buttonSize.Width,
        buttonSize.Height
      );

      Rectangle cellFilterArea = new Rectangle(cellSize.Width - buttonAreaSize.Width, 0, buttonAreaSize.Width, cellSize.Height);

      Rectangle filterButtonArea = new Rectangle(Point.Empty, buttonAreaSize);
      filterButtonArea = EhLibUtils.RectCenter(filterButtonArea, cellFilterArea);

      metric.ButtonRect = EhLibUtils.TrimPadding(filterButtonArea, metric.Margin);
    }

    public virtual void DrawInTitleFilterButton(DataGridEh dataGrid, InTitleFilterButtonArgs e)
    {
      if (Application.RenderWithVisualStyles)
      {
        if (e.PaintBack)
        {
          Rectangle btnRect = e.Rect;
          btnRect.Inflate(1, 1);
          ButtonRenderer.DrawButton(e.Graphics, btnRect, e.State);
        }
      }
      else
      {
        if (e.PaintBack)
        {
          Border3DStyle frameStyle;

          if (e.State == PushButtonState.Pressed)
            frameStyle = Border3DStyle.SunkenInner;
          else if (e.State == PushButtonState.Hot)
            frameStyle = Border3DStyle.RaisedInner;
          else
            frameStyle = Border3DStyle.Flat;

          e.Graphics.FillRectangle(new SolidBrush(SystemColors.ButtonFace), e.Rect);
          ControlPaint.DrawBorder3D(e.Graphics, e.Rect, frameStyle);
        }
      }
      DrawFilterButtonSign(dataGrid, e);
    }

    public virtual void DrawFilterButtonSign(DataGridEh dataGrid, InTitleFilterButtonArgs e)
    {
      Color fromColor, toColor;
      Point startPos;
      Rectangle signRect;

      if (e.FilterHaveData)
      {
        Bitmap bmp = Properties.Resources.TitleFilterHave2;

        signRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        signRect = EhLibUtils.RectCenter(signRect, e.Rect);

        e.Graphics.DrawImage(bmp, signRect);
      }
      else
      {
        signRect = new Rectangle(0, 0, 6, 3);
        signRect = EhLibUtils.RectCenter(signRect, e.Rect);

        fromColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.Black, 30);
        toColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.White, 00);
        startPos = new Point((signRect.Right + signRect.Left - 7) / 2 + 1,
                             (signRect.Top + signRect.Bottom - 2) / 2);

        EhLibUtils.FillGradient(e.Graphics, startPos, new Point[]
          { new Point(0, 0), new Point(7, 0),
           new Point(1, 1), new Point(6, 1),
           new Point(2, 2), new Point(5, 2),
           new Point(3, 3), new Point(4, 3)
          },
          fromColor, toColor);
      }
    }

    public virtual void DrawRowselCheckBox(Graphics g, Point location, CheckBoxState state, bool flat, bool tryUseVisualStyles)
    {
      EhLibDrawStyle.DefaultBaseElementsDrawStyle.DrawCheckBox(g, location, state, flat, tryUseVisualStyles);
    }


    //public virtual Size GetDefaultEditButtonSize(Size cellSize)
    //{
    //  Size size = new Size(SystemInformation.VerticalScrollBarWidth, SystemInformation.VerticalScrollBarWidth);

    //  size.Width = size.Width * 9 / 10;

    //  if (size.Width > cellSize.Width / 2)
    //    size.Width = cellSize.Width / 2;

    //  size.Height = size.Width * 3 / 2;
    //  if (size.Height > cellSize.Height)
    //    size.Height = cellSize.Height;

    //  return size;
    //}
  }

  public class DataVertGridDrawStyle : BaseGridDrawStyle, IDisposable
  {
    Cursor downArrowSelectCursor;
    Cursor rightArrowSelectCursor;
    readonly Padding columnOptionsSidePadding = new Padding(3, 2, 3, 2);
    private bool disposed;

    public DataVertGridDrawStyle()
    {
    }

    ~DataVertGridDrawStyle()
    {
      Dispose(false);
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (disposed)
        return;
      if (disposing)
      {
        if (downArrowSelectCursor != null) downArrowSelectCursor.Dispose();
        if (rightArrowSelectCursor != null) rightArrowSelectCursor.Dispose();
      }
      disposed = true;
    }

    public virtual bool FixFillFixedCellRect(DataVertGridEh grid, BaseGridFillFixedCellEventArgs e, ref Rectangle fillRect)
    {
      if (Application.RenderWithVisualStyles)
      {
        fillRect.Width = fillRect.Width + 2;
        fillRect.Height = fillRect.Height + 2;
        return true;
      }
      else
      {
        return false;
      }
    }

    public virtual void FillTitleCell(DataVertGridEh grid, BaseGridFillFixedCellEventArgs e)
    {
      FillFixedCell(grid, e);
    }

    public virtual void FillFixedCell(DataVertGridEh grid, BaseGridFillFixedCellEventArgs e)
    {
      base.FillFixedCell(grid, e);
    }

    public virtual Cursor DownArrowSelectCursor()
    {
      if (downArrowSelectCursor == null)
      {
        using (MemoryStream ms = new MemoryStream(Properties.Resources.DownArrowSelectCur))
        {
          downArrowSelectCursor = new Cursor(ms);
        }
      }
      return downArrowSelectCursor;
    }

    public virtual Cursor RightArrowSelectCursor()
    {
      if (rightArrowSelectCursor == null)
      {
        using (MemoryStream ms = new MemoryStream(Properties.Resources.RightArrowSelectCur))
        {
          rightArrowSelectCursor = new Cursor(ms);
        }
      }
      return rightArrowSelectCursor;
    }

    public virtual Padding GetColumnOptionsSidePadding()
    {
      return columnOptionsSidePadding;
    }

    public virtual Color GetFixedSelectedForeColor(DataVertGridEh grid, Color backColor, Color foreColor)
    {
      if (Application.RenderWithVisualStyles)
      {
        return foreColor;
      }
      else
      {
        return SystemColors.HighlightText;
      }
    }

    public virtual Size GetDefaultEditButtonSize(Size cellSize)
    {
      Size size = new Size(SystemInformation.VerticalScrollBarWidth, SystemInformation.VerticalScrollBarWidth);

      size.Width = size.Width * 9 / 10;

      if (size.Width > cellSize.Width / 2)
        size.Width = cellSize.Width / 2;

      size.Height = size.Width * 3 / 2;
      if (size.Height > cellSize.Height)
        size.Height = cellSize.Height;

      return size;
    }
  }

  public class BaseGridDrawStyle
  {

    bool applicationRenderWithVisualStyles;
    private object capturePaintControl;

    public BaseGridDrawStyle()
    {
    }

    public virtual Color DefaultBrightLineColor(BaseGridControl grid)
    {
      Color result;
      bool useVisualStyles;

      if (capturePaintControl != null)
        useVisualStyles = applicationRenderWithVisualStyles;
      else
        useVisualStyles = Application.RenderWithVisualStyles;

      if (useVisualStyles)
      {
        //VisualStyleRenderer render = new VisualStyleRenderer(VisualStyleElement.Button.PushButton.Normal);
        //return render.GetColor(ColorProperty.FillColor);
        return SystemColors.ButtonFace;
      }
      else if (grid.CanFillSelectionByTheme())
      {
        if (grid.BackColor.ToArgb() == 0xF0F0F0)
          result = Color.Gray;
        else
          result = Color.FromArgb(0xF0F0F0);
      }
      else if (grid.BackColor == Color.Silver)
        result = Color.Gray;
      else
        result = Color.Silver;

      return result;
    }

    public virtual Color DefaultDarkLineColor(BaseGridControl grid)
    {
      if ((applicationRenderWithVisualStyles && capturePaintControl != null) ||
           Application.RenderWithVisualStyles
         )
      {
        if (Environment.OSVersion.Version.Major >= 6)
        {
          VisualStyleRenderer render = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal);
          return render.GetColor(ColorProperty.EdgeFillColor);
        }
        else
        {
          return Color.FromArgb(0xCB, 0xC7, 0xB8);
        }
      }
      else
      {
        //return Color.Gray;
        return SystemColors.ButtonShadow;
      }
    }

    /// <summary> 
    /// The style that is used when Application VisualStyles are not available.
    /// </summary>
    public virtual CellFillStyle DefaultCustomFixedCellFillStyle()
    {
      return CellFillStyle.Solid;
    }

    public virtual void FillFixedCell(BaseGridControl grid, BaseGridFillFixedCellEventArgs e)
    {
      //-return;
      if (Application.RenderWithVisualStyles && e.FillStyle == CellFillStyle.VisualStyles)
      {
        VisualStyleRenderer renderer;
        Rectangle fillRect = e.CellRect;
        Region clientClip = null;
        bool clipped = false;

        if (e.IsPressed || (e.IsSelected && !e.IsHot))
          renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed);
        else if (e.IsHot)
          renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Hot);
        else
          renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal);

        if (FixFillFixedCellRect(grid, e, ref fillRect))
        {
          clientClip = grid.PaintingSetClip(e.Graphics, e.CellRect, CombineMode.Intersect);
          //clientClip = e.Graphics.Clip;
          //e.Graphics.SetClip(e.CellRect, CombineMode.Intersect);
          clipped = true;
        }
        if (grid.UseRightToLeft)
          fillRect = EhLibUtils.RightToLeftFlipRectangle(grid.ClientRectangle, fillRect);
        renderer.DrawBackground(e.Graphics, fillRect);
        if (clipped)
        {
          grid.PaintingSetClip(e.Graphics, clientClip, CombineMode.Replace);
          //e.Graphics.Clip = clientClip;
        }
      }
      else
      {
        CellFillStyle fillStyle;
        Rectangle fillRect = e.CellRect;

        if (e.FillStyle == CellFillStyle.VisualStyles)
          fillStyle = DefaultCustomFixedCellFillStyle();
        else
          fillStyle = e.FillStyle;

        if (grid.UseRightToLeft)
          fillRect = EhLibUtils.RightToLeftFlipRectangle(grid.ClientRectangle, fillRect);

        if (fillStyle == CellFillStyle.Solid)
        {
          Color color = e.BackColor;
          if (e.IsSelected)
          {
            color = SystemColors.Highlight;
            float h = color.GetHue();
            float s = color.GetSaturation();
            float b = color.GetBrightness();
            color = EhLibUtils.ColorFromAHSB(255, h, s / 6, b);
          }
          using (SolidBrush fillBrush = new SolidBrush(color))
          {
            e.Graphics.FillRectangle(fillBrush, fillRect);
          }
        }
        else if (fillStyle == CellFillStyle.VertGradient)
        {
          EhLibUtils.FillRectangleGradient(e.Graphics, fillRect, e.SecondFillColor, e.FillColor);
        }

        if (e.InnerBorder == CellInnerBorderStyle.RaisedTopLeft)
        {
          Border3DStyle style;
          if (e.IsPressed)
            style = Border3DStyle.SunkenInner;
          else
            style = Border3DStyle.RaisedInner;
          ControlPaint.DrawBorder3D(e.Graphics, fillRect, style, Border3DSide.Left | Border3DSide.Top);
        }
        else if (e.InnerBorder == CellInnerBorderStyle.RaisedFull)
        {
          Border3DStyle style = Border3DStyle.RaisedInner;
          ControlPaint.DrawBorder3D(e.Graphics, fillRect, style);
        }
      }
    }

    public virtual bool FixFillFixedCellRect(BaseGridControl grid, BaseGridFillFixedCellEventArgs e, ref Rectangle fillRect)
    {
      if (Application.RenderWithVisualStyles)
      {
        fillRect.Width = fillRect.Width + 2;
        fillRect.Height = fillRect.Height + 2;
        return true;
      }
      else
      {
        return false;
      }
    }

    protected virtual void RefreshDrawBuffer()
    {
      applicationRenderWithVisualStyles = Application.RenderWithVisualStyles;
    }

    public virtual void CapturePaint(Control control)
    {
      if (capturePaintControl == null)
      {
        capturePaintControl = control;
        RefreshDrawBuffer();
      }
    }

    public virtual void  ReleasePaint(Control control)
    {
      if (capturePaintControl == control)
        capturePaintControl = null;
    }
  }

  //TextBoxRenderStyle
  public class TextBoxDrawStyle
  {

    private readonly bool textBoxNoScrollElementChecked = false;
    private bool textBoxNoScrollElementIsDefined;

    private VisualStyleRenderer visualStyleRenderer;
    private readonly VisualStyleElement textBoxElement = VisualStyleElement.TextBox.TextEdit.Normal;
    private static readonly VisualStyleElement TextBoxNoScrollElement =
      VisualStyleElement.CreateElement("EDIT",
                                       (int)EDITPARTS.EP_EDITBORDER_NOSCROLL,
                                       (int)EDITBORDER_NOSCROLLSTATES.EPSN_NORMAL);

    public TextBoxDrawStyle()
    {
    }

    protected void CheckElements()
    {
      if (textBoxNoScrollElementChecked) return;
      textBoxNoScrollElementIsDefined = VisualStyleRenderer.IsElementDefined(TextBoxNoScrollElement);
    }

    public virtual VisualStyleElement TextBoxElement()
    {
      CheckElements();
      if (textBoxNoScrollElementIsDefined)
        return TextBoxNoScrollElement;
      else
        return textBoxElement;
    }

    public virtual TextBoxState GetTextBoxState(bool isHot, bool isSelected, bool isDisabled, bool isReadonly)
    {
      if (isDisabled)
        return TextBoxState.Disabled;
      else if (isReadonly)
        return TextBoxState.Readonly;
      else if (isSelected)
        return TextBoxState.Selected;
      else if (isHot)
        return TextBoxState.Hot;
      else
        return TextBoxState.Normal;
      //Assist = 7
    }

    public virtual void DrawTextBoxFrame(Graphics g, Rectangle bounds, TextBoxState state, Control childControl, BorderStyle borderStyle)
    {
      if (borderStyle == BorderStyle.None) return;

      if (Application.RenderWithVisualStyles && borderStyle == BorderStyle.Fixed3D)
      {
        if (visualStyleRenderer == null)
        {
          visualStyleRenderer = new VisualStyleRenderer(TextBoxElement().ClassName, TextBoxElement().Part, (int)state);
        }
        else
        {
          visualStyleRenderer.SetParameters(TextBoxElement().ClassName, TextBoxElement().Part, (int)state);
        }

        if (visualStyleRenderer.IsBackgroundPartiallyTransparent() && (childControl != null))
          visualStyleRenderer.DrawParentBackground(g, bounds, childControl);
        visualStyleRenderer.DrawBackground(g, bounds);
      }
      else
      {
        if (borderStyle == BorderStyle.Fixed3D)
          ControlPaint.DrawBorder3D(g, bounds, Border3DStyle.Sunken);
        else
          ControlPaint.DrawBorder(g, bounds, SystemColors.ControlDarkDark, ButtonBorderStyle.Solid);
        //visualStyleRenderer.DrawEdge(e.Graphics, bounds, Edges.Left | Edges.Right | Edges.Top | Edges.Bottom, EdgeStyle.Sunken, EdgeEffects.None);
        //ControlPaint.DrawBorder(g, bounds, SystemColors.ButtonFace, ButtonBorderStyle.Dashed);
      }
    }

  }

  public class ToolElementsDrawStyle
  {

    public ToolElementsDrawStyle()
    {
    }

    public virtual void DrawPushButtonBack(Graphics g, PushButtonBackDrawArgs e)
    {
      if (Application.RenderWithVisualStyles ||
          (e.ParentHasFrame && e.BorderStyle == PushButtonBorderStyle.Thick))
      {
        Rectangle btnRect = e.Rect;

        if (Application.RenderWithVisualStyles)
          btnRect.Inflate(1, 1);
        ButtonRenderer.DrawButton(e.Graphics, btnRect, e.State);
      }
      else
      {
        Border3DStyle frameStyle;
        Rectangle innerRect = e.Rect;
        innerRect.Inflate(-1, -1);

        e.Graphics.FillRectangle(new SolidBrush(SystemColors.ButtonFace), innerRect);

        if (e.ParentHasFrame && e.BorderStyle == PushButtonBorderStyle.Thin)
        {
          if (e.State == PushButtonState.Pressed)
            frameStyle = Border3DStyle.SunkenInner;
          else
            frameStyle = Border3DStyle.RaisedInner;
        }
        else
        {
          if (e.State == PushButtonState.Pressed)
            frameStyle = Border3DStyle.SunkenInner;
          else if (e.State == PushButtonState.Hot)
            frameStyle = Border3DStyle.RaisedInner;
          else
            frameStyle = Border3DStyle.Adjust;
        }
        ControlPaint.DrawBorder3D(e.Graphics, e.Rect, frameStyle);
      }
    }

    public virtual void DrawDropDownButtonSign(Graphics g, Rectangle bounds, PushButtonState state)
    {
      Rectangle signRect = new Rectangle(0, 0, 6, 3);
      signRect = EhLibUtils.RectCenter(signRect, bounds);

      Color fromColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.Black, 30);
      Color toColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.White, 00);
      Point startPos = new Point((signRect.Right + signRect.Left - 7) / 2 + 1,
                           (signRect.Top + signRect.Bottom - 2) / 2);

      EhLibUtils.FillGradient(g, startPos, new Point[]
        { new Point(0, 0), new Point(7, 0),
           new Point(1, 1), new Point(6, 1),
           new Point(2, 2), new Point(5, 2),
           new Point(3, 3), new Point(4, 3)
        },
        fromColor, toColor);
    }

    public virtual void DrawEllipsisButtonSign(Graphics g, Rectangle bounds, PushButtonState state)
    {
      Rectangle signRect = new Rectangle(0, 0, 10, 2);
      signRect = EhLibUtils.RectCenter(signRect, bounds);

      Color fromColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.Black, 30);
      Color toColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.White, 00);
      Point startPos = signRect.Location;

      EhLibUtils.FillGradient(g, startPos, new Point[]
        { new Point(0, 0), new Point(2, 0),
           new Point(0, 1), new Point(2, 1),
        },
        fromColor, toColor);

      EhLibUtils.FillGradient(g, startPos, new Point[]
        { new Point(4, 0), new Point(6, 0),
           new Point(4, 1), new Point(6, 1),
        },
        fromColor, toColor);

      EhLibUtils.FillGradient(g, startPos, new Point[]
        { new Point(8, 0), new Point(10, 0),
           new Point(8, 1), new Point(10, 1),
        },
        fromColor, toColor);

    }

    public virtual Font GetRefLinkFont(Font font)
    {
      return new Font(font, FontStyle.Underline);
    }

    public virtual Color GetRefLinkFontColor()
    {
      return SystemColors.HotTrack;
    }

  }

  public enum ProgressBarTextType
    { AsValue, AsPercent };

  //public enum ProgressBarFrameFigureType
  //  { Rectangle, RoundRect };

  public enum ProgressBarFrameSizeType
    { Full, Val };

  public class ProgressBarPaintEventArgs : EventArgs
  {

    public ProgressBarPaintEventArgs()
    {
      ShowText = true;
      TextType = ProgressBarTextType.AsPercent;
      TextDecimalPlaces = 0;
      Indent = 1;
      //FrameFigureType = ProgressBarFrameFigureType.Rectangle;
      FrameSizeType = ProgressBarFrameSizeType.Val;
      Font = null;
      TextAlignment = HorizontalAlignment.Center;
    }

    public virtual void ResetProperties()
    {
      ShowText = true;
      TextType = ProgressBarTextType.AsPercent;
      TextDecimalPlaces = 0;
      Indent = 1;
      //FrameFigureType = ProgressBarFrameFigureType.Rectangle;
      FrameSizeType = ProgressBarFrameSizeType.Val;
      Font = null;
      TextAlignment = HorizontalAlignment.Center;
    }

    public double CurrentValue { get; set; }
    public double MinValue { get; set; }
    public double MaxValue { get; set; }

    public Color ForeColor { get; set; }
    public Color FrameColor { get; set; }
    public Color BackgroundColor { get; set; }
    public Color TextColor { get; set; }
    public Color OutbarTextColor { get; set; }

    public bool ShowText { get; set; }

    public ProgressBarTextType TextType { get; set; }
    public int TextDecimalPlaces { get; set; }
    public HorizontalAlignment TextAlignment { get; set; }
    //public ProgressBarFrameFigureType FrameFigureType { get; set; }
    public ProgressBarFrameSizeType FrameSizeType { get; set; }
    public int Indent { get; set; }
    public Font Font { get; set; }
  }

  public class ProgressBarDrawStyle
  {

    public ProgressBarDrawStyle()
    {
    }

    public virtual ProgressBarPaintEventArgs CreateProgressBarPaintArgs()
    {
      return new ProgressBarPaintEventArgs();
    }

    public virtual void DrawBar(Graphics g, Rectangle bounds, ProgressBarPaintEventArgs args)
    {
      Rectangle progressFrameRect;
      Rectangle completeRect;
      //int progressPosition;
      int progressWidth;
      string progressText;
      //Size textSize;
      Rectangle textRect;
      double maxValue;
      double curValue;
      bool clipBarText;

      if (args.BackgroundColor != Color.Empty)
      {
        using (SolidBrush brush = new SolidBrush(args.BackgroundColor))
        {
          g.FillRectangle(brush, bounds);
        }
      }

      progressFrameRect = bounds;
      progressFrameRect.Inflate(-args.Indent, -args.Indent);
      progressFrameRect.Width = progressFrameRect.Width - 1;
      progressFrameRect.Height = progressFrameRect.Height - 1;

      maxValue = Math.Abs(args.MaxValue - args.MinValue);
      curValue = Math.Abs(args.CurrentValue - args.MinValue);
      //if (CurValue < 0) CurValue = 0;
      //if (CurValue > maxValue) CurValue = 0;
      if (maxValue == 0) return;
      progressWidth = (int)Math.Round(curValue / maxValue * progressFrameRect.Width);

      if (progressWidth < 0) progressWidth = 0;
      if (progressWidth > progressFrameRect.Width) progressWidth = progressFrameRect.Width;

      completeRect = progressFrameRect;
      completeRect.Width = progressWidth;
      if (args.FrameSizeType == ProgressBarFrameSizeType.Val)
        progressFrameRect.Width = progressWidth;

      if (args.TextType == ProgressBarTextType.AsValue)
        progressText = Math.Round(args.CurrentValue, -args.TextDecimalPlaces).ToString(CultureInfo.CurrentCulture);
      else
        progressText = Math.Round(args.CurrentValue / (args.MaxValue - args.MinValue) * 100, args.TextDecimalPlaces) + "%";
      textRect = bounds;

      if (args.TextColor != args.OutbarTextColor)
      {
        if (args.ShowText)
          EhLibUtils.DrawText(g, progressText, args.Font, textRect, args.OutbarTextColor, args.TextAlignment, VerticalAlignment.Center, TextFormatFlagsEh.None);
        clipBarText = true;
      }
      else
        clipBarText = false;
      //if (args.FrameSizeType == ProgressBarFrameSizeType.Full)
      {
        using (SolidBrush brush = new SolidBrush(args.ForeColor))
        {
          g.FillRectangle(brush, completeRect);
        }

        using (Pen pen = new Pen(args.FrameColor))
        {
          g.DrawRectangle(pen, progressFrameRect);
        }
      }

      if (args.ShowText)
      {
        Region oldClip = null;

        if (clipBarText)
        {
          oldClip = g.Clip;
          g.SetClip(progressFrameRect, CombineMode.Intersect);
        }

        EhLibUtils.DrawText(g, progressText, args.Font, textRect, args.TextColor, args.TextAlignment, VerticalAlignment.Center, TextFormatFlagsEh.None);

        if (clipBarText)
        {
          if (oldClip != null)
            g.Clip = oldClip;
        }
      }
    }

    public virtual void FillProgressBarPaintArgsDefaultValues(ProgressBarPaintEventArgs args)
    {
      args.BackgroundColor = SystemColors.Window;
      args.FrameColor = SystemColors.ControlDarkDark;
      args.ForeColor = Color.FromArgb(0xA6, 0xCA, 0xF0);//Color.SkyBlue;

      args.ShowText = true;
      args.TextType = ProgressBarTextType.AsPercent;
      args.TextDecimalPlaces = 0;
      args.Indent = 1;
      //FrameFigureType = ProgressBarFrameFigureType.Rectangle;
      args.FrameSizeType = ProgressBarFrameSizeType.Val;
      args.Font = null;
      args.TextAlignment = HorizontalAlignment.Center;

    }
  }

}
