context: using System;
  using System.Collections.Generic;
  using System.Drawing;
  using System.Windows.Forms;
  
  namespace mRemoteNG.UI.TaskDialog
  {
      public partial class frmTaskDialog : Form
      {
          //--------------------------------------------------------------------------------
          #region PRIVATE members
          //--------------------------------------------------------------------------------
  
          private string _mainInstruction = "Main Instruction Text";
          private int _mainInstructionHeight;
          private readonly Font _mainInstructionFont = new Font("Segoe UI", 11.75F, FontStyle.Regular, GraphicsUnit.Point, 0);
  
          private readonly List<RadioButton> _radioButtonCtrls = new List<RadioButton>();
  
          private Control _focusControl;
  
          private bool _isVista = false;
          #endregion
  
          //--------------------------------------------------------------------------------
          #region PROPERTIES
          //--------------------------------------------------------------------------------
          public ESysIcons MainIcon { get; set; } = ESysIcons.Question;
          public ESysIcons FooterIcon { get; set; } = ESysIcons.Warning;
  
          public string Title { get { return Text; } set { Text = value; } }
          public string MainInstruction { get { return _mainInstruction; } set { _mainInstruction = value; Invalidate(); } }
          public string Content { get { return lbContent.Text; } set { lbContent.Text = value; } }
          public string ExpandedInfo { get { return lbExpandedInfo.Text; } set { lbExpandedInfo.Text = value; } }
          public string Footer { get { return lbFooter.Text; } set { lbFooter.Text = value; } }
          public int DefaultButtonIndex { get; set; }
  
          public string RadioButtons { get; set; } = "";
  
          public int RadioButtonIndex
          {
              get
              {
                  foreach (var rb in _radioButtonCtrls)
                      if (rb.Checked)
                          return (int)rb.Tag;
                  return -1;
              }
          }
  
          public string CommandButtons { get; set; } = "";
          public int CommandButtonClickedIndex { get; private set; } = -1;
  
          public ETaskDialogButtons Buttons { get; set; } = ETaskDialogButtons.YesNoCancel;
  
          public string VerificationText { get { return cbVerify.Text; } set { cbVerify.Text = value; } }
          public bool VerificationCheckBoxChecked { get { return cbVerify.Checked; } set { cbVerify.Checked = value; } }
  
          private bool Expanded { get; set; }
  
          #endregion
  
          //--------------------------------------------------------------------------------
          #region CONSTRUCTOR
          //--------------------------------------------------------------------------------
          public frmTaskDialog()
          {
              InitializeComponent();
  
              // _isVista = VistaTaskDialog.IsAvailableOnThisOS;
              if (!_isVista && CTaskDialog.UseToolWindowOnXp) // <- shall we use the smaller toolbar?
                  FormBorderStyle = FormBorderStyle.FixedToolWindow;
  
              MainInstruction = "Main Instruction";
              Content = "";
              ExpandedInfo = "";
              Footer = "";
              VerificationText = "";
          }
          #endregion
  
          //--------------------------------------------------------------------------------
          #region BuildForm
          // This is the main routine that should be called before .ShowDialog()
          //--------------------------------------------------------------------------------
          private bool _formBuilt;
          public void BuildForm()
          {
              var form_height = 0;
  
              // Setup Main Instruction
              switch (MainIcon)
              {
                  case ESysIcons.Information: imgMain.Image = SystemIcons.Information.ToBitmap(); break;
                  case ESysIcons.Question: imgMain.Image = SystemIcons.Question.ToBitmap(); break;
                  case ESysIcons.Warning: imgMain.Image = SystemIcons.Warning.ToBitmap(); break;
                  case ESysIcons.Error: imgMain.Image = SystemIcons.Error.ToBitmap(); break;
                  default:
                      throw new ArgumentOutOfRangeException();
              }
  
              //AdjustLabelHeight(lbMainInstruction);
              //pnlMainInstruction.Height = Math.Max(41, lbMainInstruction.Height + 16);
              if (_mainInstructionHeight == 0)
                  GetMainInstructionTextSizeF();
              pnlMainInstruction.Height = Math.Max(41, _mainInstructionHeight + 16);
  
              form_height += pnlMainInstruction.Height;
  
              // Setup Content
              pnlContent.Visible = (Content != "");
              if (Content != "")
              {
                  AdjustLabelHeight(lbContent);
                  pnlContent.Height = lbContent.Height + 4;
                  form_height += pnlContent.Height;
              }
  
              var show_verify_checkbox = (cbVerify.Text != "");
              cbVerify.Visible = show_verify_checkbox;
  
              // Setup Expanded Info and Buttons panels
              if (ExpandedInfo == "")
              {
                  pnlExpandedInfo.Visible = false;
                  lbShowHideDetails.Visible = false;
                  cbVerify.Top = 12;
                  pnlButtons.Height = 40;
              }
              else
              {
                  AdjustLabelHeight(lbExpandedInfo);
                  pnlExpandedInfo.Height = lbExpandedInfo.Height + 4;
                  pnlExpandedInfo.Visible = Expanded;
                  lbShowHideDetails.Text = (Expanded ? "        Hide details" : "        Show details");
                  lbShowHideDetails.ImageIndex = (Expanded ? 0 : 3);
                  if (!show_verify_checkbox)
                      pnlButtons.Height = 40;
                  if (Expanded)
                      form_height += pnlExpandedInfo.Height;
              }
  
              // Setup RadioButtons
              pnlRadioButtons.Visible = (RadioButtons != "");
              if (RadioButtons != "")
              {
                  var arr = RadioButtons.Split(new char[] { '|' });
                  var pnl_height = 12;
                  for (var i = 0; i < arr.Length; i++)
                  {
                      var rb = new RadioButton();
                      rb.Parent = pnlRadioButtons;
                      rb.Location = new Point(60, 4 + (i * rb.Height));
                      rb.Text = arr[i];
                      rb.Tag = i;
                      rb.Checked = (DefaultButtonIndex == i);
                      rb.Width = Width - rb.Left - 15;
                      pnl_height += rb.Height;
                      _radioButtonCtrls.Add(rb);
                  }
                  pnlRadioButtons.Height = pnl_height;
                  form_height += pnlRadioButtons.Height;
              }
  
              // Setup CommandButtons
              pnlCommandButtons.Visible = (CommandButtons != "");
              if (CommandButtons != "")
              {
                  var arr = CommandButtons.Split(new char[] { '|' });
                  var t = 8;
                  var pnl_height = 16;
                  for (var i = 0; i < arr.Length; i++)
                  {
                      var btn = new CommandButton();
                      btn.Parent = pnlCommandButtons;
                      btn.Location = new Point(50, t);
                      if (_isVista)  // <- tweak font if vista
                          btn.Font = new Font(btn.Font, FontStyle.Regular);
                      btn.Text = arr[i];
                      btn.Size = new Size(Width - btn.Left - 15, btn.GetBestHeight());
                      t += btn.Height;
                      pnl_height += btn.Height;
                      btn.Tag = i;
                      btn.Click += new EventHandler(CommandButton_Click);
                      if (i == DefaultButtonIndex)
                          _focusControl = btn;
                  }
                  pnlCommandButtons.Height = pnl_height;
                  form_height += pnlCommandButtons.Height;
              }
  
              // Setup Buttons
              switch (Buttons)
              {
                  case ETaskDialogButtons.YesNo:
                      bt1.Visible = false;
                      bt2.Text = "&Yes";
                      bt2.DialogResult = DialogResult.Yes;
                      bt3.Text = "&No";
                      bt3.DialogResult = DialogResult.No;
                      AcceptButton = bt2;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.YesNoCancel:
                      bt1.Text = "&Yes";
                      bt1.DialogResult = DialogResult.Yes;
                      bt2.Text = "&No";
                      bt2.DialogResult = DialogResult.No;
                      bt3.Text = "&Cancel";
                      bt3.DialogResult = DialogResult.Cancel;
                      AcceptButton = bt1;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.OkCancel:
                      bt1.Visible = false;
                      bt2.Text = "&OK";
                      bt2.DialogResult = DialogResult.OK;
                      bt3.Text = "&Cancel";
                      bt3.DialogResult = DialogResult.Cancel;
                      AcceptButton = bt2;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.Ok:
                      bt1.Visible = false;
                      bt2.Visible = false;
                      bt3.Text = "&OK";
                      bt3.DialogResult = DialogResult.OK;
                      AcceptButton = bt3;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.Close:
                      bt1.Visible = false;
                      bt2.Visible = false;
                      bt3.Text = "&Close";
                      bt3.DialogResult = DialogResult.Cancel;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.Cancel:
                      bt1.Visible = false;
                      bt2.Visible = false;
                      bt3.Text = "&Cancel";
                      bt3.DialogResult = DialogResult.Cancel;
                      CancelButton = bt3;
                      break;
                  case ETaskDialogButtons.None:
                      bt1.Visible = false;
                      bt2.Visible = false;
                      bt3.Visible = false;
                      break;
                  default:
                      throw new ArgumentOutOfRangeException();
              }
  
              ControlBox = (Buttons == ETaskDialogButtons.Cancel ||
                                 Buttons == ETaskDialogButtons.Close ||
                                 Buttons == ETaskDialogButtons.OkCancel ||
                                 Buttons == ETaskDialogButtons.YesNoCancel);
  
              if (!show_verify_checkbox && ExpandedInfo == "" && Buttons == ETaskDialogButtons.None)
                  pnlButtons.Visible = false;
              else
                  form_height += pnlButtons.Height;
  
              pnlFooter.Visible = (Footer != "");
              if (Footer != "")
              {
                  AdjustLabelHeight(lbFooter);
                  pnlFooter.Height = Math.Max(28, lbFooter.Height + 16);
                  switch (FooterIcon)
                  {
                      case ESysIcons.Information:
                          // SystemIcons.Information.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                          imgFooter.Image = ResizeBitmap(SystemIcons.Information.ToBitmap(), 16, 16);
                          break;
                      case ESysIcons.Question:
                          // SystemIcons.Question.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                          imgFooter.Image = ResizeBitmap(SystemIcons.Question.ToBitmap(), 16, 16);
                          break;
                      case ESysIcons.Warning:
                          // SystemIcons.Warning.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                          imgFooter.Image = ResizeBitmap(SystemIcons.Warning.ToBitmap(), 16, 16);
                          break;
                      case ESysIcons.Error:
                          // SystemIcons.Error.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                          imgFooter.Image = ResizeBitmap(SystemIcons.Error.ToBitmap(), 16, 16);
                          break;
                      default:
                          throw new ArgumentOutOfRangeException();
                  }
                  form_height += pnlFooter.Height;
              }
  
              ClientSize = new Size(ClientSize.Width, form_height);
  
              _formBuilt = true;
          }
  
          //--------------------------------------------------------------------------------
          private static Image ResizeBitmap(Image SrcImg, int NewWidth, int NewHeight)
          {
              var percent_width = (NewWidth / (float)SrcImg.Width);
              var percent_height = (NewHeight / (float)SrcImg.Height);
  
              var resize_percent = (percent_height < percent_width ? percent_height : percent_width);
  
              var w = (int)(SrcImg.Width * resize_percent);
              var h = (int)(SrcImg.Height * resize_percent);
              var b = new Bitmap(w, h);
  
              using (var g = Graphics.FromImage(b))
              {
                  g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                  g.DrawImage(SrcImg, 0, 0, w, h);
              }
              return b;
          }
  
          //--------------------------------------------------------------------------------
          // utility function for setting a Label's height
          private static void AdjustLabelHeight(Control lb)
          {
              var text = lb.Text;
              var textFont = lb.Font;
              var layoutSize = new SizeF(lb.ClientSize.Width, 5000.0F);
              var g = Graphics.FromHwnd(lb.Handle);
              var stringSize = g.MeasureString(text, textFont, layoutSize);
              lb.Height = (int)stringSize.Height + 4;
              g.Dispose();
          }
          #endregion
  
          //--------------------------------------------------------------------------------
          #region EVENTS
          //--------------------------------------------------------------------------------
          private void CommandButton_Click(object sender, EventArgs e)
          {
              CommandButtonClickedIndex = (int)((CommandButton)sender).Tag;
              DialogResult = DialogResult.OK;
          }
  
  
          //--------------------------------------------------------------------------------
          protected override void OnShown(EventArgs e)
          {
              if (!_formBuilt)
                  throw new Exception("frmTaskDialog : Please call .BuildForm() before showing the TaskDialog");
              base.OnShown(e);
          }
  
          //--------------------------------------------------------------------------------
          private void lbDetails_MouseEnter(object sender, EventArgs e)
          {
              lbShowHideDetails.ImageIndex = (Expanded ? 1 : 4);
          }
  
          //--------------------------------------------------------------------------------
          private void lbDetails_MouseLeave(object sender, EventArgs e)
          {
              lbShowHideDetails.ImageIndex = (Expanded ? 0 : 3);
          }
  
          //--------------------------------------------------------------------------------
          private void lbDetails_MouseUp(object sender, MouseEventArgs e)
          {
              lbShowHideDetails.ImageIndex = (Expanded ? 1 : 4);
          }
  
          //--------------------------------------------------------------------------------
          private void lbDetails_MouseDown(object sender, MouseEventArgs e)
          {
              lbShowHideDetails.ImageIndex = (Expanded ? 2 : 5);
          }
  
          //--------------------------------------------------------------------------------
          private void lbDetails_Click(object sender, EventArgs e)
          {
              Expanded = !Expanded;
              pnlExpandedInfo.Visible = Expanded;
              lbShowHideDetails.Text = (Expanded ? "        Hide details" : "        Show details");
              if (Expanded)
                  Height += pnlExpandedInfo.Height;
              else
                  Height -= pnlExpandedInfo.Height;
          }
  
          //--------------------------------------------------------------------------------
          private const int MAIN_INSTRUCTION_LEFT_MARGIN = 46;
          private const int MAIN_INSTRUCTION_RIGHT_MARGIN = 8;
  
          private SizeF GetMainInstructionTextSizeF()
          {
              var mzSize = new SizeF(pnlMainInstruction.Width - MAIN_INSTRUCTION_LEFT_MARGIN - MAIN_INSTRUCTION_RIGHT_MARGIN, 5000.0F);
              var g = Graphics.FromHwnd(Handle);
              var textSize = g.MeasureString(_mainInstruction, _mainInstructionFont, mzSize);
              _mainInstructionHeight = (int)textSize.Height;
              return textSize;
          }
  
          private void pnlMainInstruction_Paint(object sender, PaintEventArgs e)
          {
              var szL = GetMainInstructionTextSizeF();
              e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
              e.Graphics.DrawString(_mainInstruction, _mainInstructionFont, new SolidBrush(Color.DarkBlue), new RectangleF(new PointF(MAIN_INSTRUCTION_LEFT_MARGIN, 10), szL));
          }
  
          //--------------------------------------------------------------------------------
          private void frmTaskDialog_Shown(object sender, EventArgs e)
          {
              if (CTaskDialog.PlaySystemSounds)
              {
                  switch (MainIcon)
                  {
                      case ESysIcons.Error: System.Media.SystemSounds.Hand.Play(); break;
                      case ESysIcons.Information: System.Media.SystemSounds.Asterisk.Play(); break;
                      case ESysIcons.Question: System.Media.SystemSounds.Asterisk.Play(); break;
                      case ESysIcons.Warning: System.Media.SystemSounds.Exclamation.Play(); break;
                      default:
  
gt:                         throw new ArgumentOutOfRangeException();