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

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace EhLib
{
  public enum BevelStyle
  {
    Lowered,
    Raised
  }

  public enum BevelType 
  {
    Box, 
    Frame, 
    TopLine, 
    BottomLine, 
    LeftLine,
    RightLine, 
    Spacer                      
  }

  [DesignerCategory("Code")]
  [ToolboxItem(false)]
  public class BevelControl : Control
  {
    #region private members
    private BevelStyle bevelStyle = BevelStyle.Lowered;
    private BevelType bevelType = BevelType.Box;
    private Color shadowColor = SystemColors.ButtonShadow;
    private Color highlightColor = SystemColors.ButtonHighlight;
    #endregion

    #region protected methods
    protected virtual Pen GetPen(int index)
    {
      Color color;

      if (index.Equals(0))
        color = bevelStyle.Equals(BevelStyle.Lowered) ? shadowColor : highlightColor;
      else
        color = bevelStyle.Equals(BevelStyle.Lowered) ? highlightColor : shadowColor;

      return new Pen(color);
    }

    protected virtual void BevelRect(Graphics graphics, Rectangle rect)
    {
      using (Pen pen = GetPen(0))
      {
        graphics.DrawLine(pen, rect.Left, rect.Bottom, rect.Left, rect.Top);
        graphics.DrawLine(pen, rect.Left, rect.Top, rect.Right, rect.Top);
      }
      using (Pen pen = GetPen(1))
      {
        graphics.DrawLine(pen, rect.Right, rect.Top, rect.Right, rect.Bottom);
        graphics.DrawLine(pen, rect.Right, rect.Bottom, rect.Left, rect.Bottom);
      }
    }

    protected virtual void FrameRect(Graphics graphics, Rectangle rect)
    {
      using (Pen pen = GetPen(1))
        graphics.DrawRectangle(pen, rect);

      rect = new Rectangle(rect.Left - 1, rect.Top - 1, rect.Width, rect.Height);
      using (Pen pen = GetPen(0))
        graphics.DrawRectangle(pen, rect);
    }

    protected virtual void BevelLine(Pen pen, Graphics graphics, int x1, int y1, int x2, int y2)
    {
      graphics.DrawLine(pen, x1, y1, x2, y2);
    }

    protected virtual void SpacerRect(Graphics graphics, Rectangle rect)
    {
      using (Pen pen = new Pen(Color.Black))
      {
        pen.DashStyle = DashStyle.Dot;
        graphics.DrawRectangle(pen, rect);
      }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
      // Calling the base class OnPaint
      base.OnPaint(e);

      switch (bevelType)
      {
        case BevelType.Box:
          BevelRect(e.Graphics, new Rectangle(0, 0, Width - 1, Height - 1));
          break;
        case BevelType.Frame:
          FrameRect(e.Graphics, new Rectangle(1, 1, Width - 2, Height - 2));
          break;
        case BevelType.TopLine:
          using (Pen pen = GetPen(0))
            BevelLine(pen, e.Graphics, 0, 0, Width, 0);
          using (Pen pen = GetPen(1))
            BevelLine(pen, e.Graphics, 0, 1, Width, 1);
          break;
        case BevelType.BottomLine:
          using (Pen pen = GetPen(0))
            BevelLine(pen, e.Graphics, 0, Height - 2, Width, Height - 2);
          using (Pen pen = GetPen(1))
            BevelLine(pen, e.Graphics, 0, Height - 1, Width, Height - 1);
          break;
        case BevelType.LeftLine:
          using (Pen pen = GetPen(0))
            BevelLine(pen, e.Graphics, 0, 0, 0, Height);
          using (Pen pen = GetPen(1))
            BevelLine(pen, e.Graphics, 1, 0, 1, Height);
          break;
        case BevelType.RightLine:
          using (Pen pen = GetPen(0))
            BevelLine(pen, e.Graphics, Width - 2, 0, Width - 2, Height);
          using (Pen pen = GetPen(1))
            BevelLine(pen, e.Graphics, Width - 1, 0, Width - 1, Height);
          break;
        case BevelType.Spacer:
          if (DesignMode)
            SpacerRect(e.Graphics, new Rectangle(0, 0, Width - 1, Height - 1));
          break;
      }            
    }
    #endregion

    #region public properties
    [Category("Bevel")]
    public BevelStyle BevelStyle
    {
      get { return bevelStyle; }
      set { bevelStyle = value; Refresh(); }
    }

    [Category("Bevel")]
    public BevelType BevelType
    {
      get { return bevelType; }
      set { bevelType = value; Refresh(); }
    }

    [Category("Bevel")]
    [Browsable(true)]
    public Color HighlightColor
    {
      get { return highlightColor; }
      set { highlightColor = value; Refresh(); }
    }

    [Category("Bevel")]
    [Browsable(true)]
    public Color ShadowColor
    {
      get { return shadowColor; }
      set { shadowColor = value; Refresh(); }
    }
    #endregion
  }
}
