diff ServerMonitor/Forms/CheckForm.cs @ 0:3e1a2131f897

Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
author Brad Greco <brad@bgreco.net>
date Mon, 31 Dec 2018 18:32:14 -0500
parents
children 9e92780ebc0f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Forms/CheckForm.cs	Mon Dec 31 18:32:14 2018 -0500
@@ -0,0 +1,336 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace ServerMonitorApp
+{
+    public partial class CheckForm : Form
+    {
+        //private static readonly Dictionary<Type, CheckInfo> checkInfo = new Dictionary<Type, CheckInfo>();
+        private readonly List<CheckControl> checkControls = new List<CheckControl>();
+        private bool helpShown;
+        private CancellationTokenSource cancellationTokenSource;
+        private Check workCheck;
+        private CheckControl checkControl;
+        private QuickHelpForm helpForm;
+        private Server server;
+        private ServerMonitor monitor;
+
+        public event EventHandler<HelpLocationChangedEventArgs> HelpLocationChanged;
+
+        public Check Check { get; private set; }
+
+        public int CheckId { get; private set; }
+
+        public Point HelpLocation { get { return TypeHelpPictureBox.PointToScreen(Point.Empty); } }
+
+        public CheckForm(ServerMonitor monitor, Check check)
+        {
+            InitializeComponent();
+
+            Check = check;
+            CheckId = Check.Id;
+            server = Check.Server;
+            this.monitor = monitor;
+        }
+
+        public CheckForm(ServerMonitor monitor, Server server)
+        {
+            InitializeComponent();
+            this.server = server;
+            this.monitor = monitor;
+        }
+
+        private void CheckForm_Load(object sender, EventArgs e)
+        {
+            CheckTypeComboBox.Items.AddRange(Check.CheckTypes);
+            FrequencyUnitsComboBox.DataSource = Enum.GetValues(typeof(FrequencyUnits));
+            Helpers.FormatImageButton(RunButton);
+            Helpers.FormatImageButton(CancelRunButton);
+
+            Move += CheckForm_Move;
+            CheckTypePanel.LocationChanged += CheckTypePanel_LocationChanged;
+            GeneralGroupBox.Click += Control_Click;
+            CheckSettingsPanel.Click += Control_Click;
+
+            CheckTypeComboBox.SelectedItem = Check?.GetType();
+            if (Check != null)
+                LoadCheck(Check);
+        }
+
+        private void CheckTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            ShowCheckControl();
+            workCheck = (Check)Activator.CreateInstance((Type)CheckTypeComboBox.SelectedItem);
+        }
+
+        private void CheckTypeComboBox_Format(object sender, ListControlConvertEventArgs e)
+        {
+            e.Value = Helpers.GetDisplayName((Type)e.ListItem);
+        }
+
+        /*private void showGroupBox(GroupBox groupBox)
+        {
+
+        }*/
+
+        /*private Type GetCheckType()
+        {
+            return (Type)CheckTypeComboBox.SelectedItem;
+        }*/
+
+        private void ShowCheckControl()
+        {
+            IEnumerable<CheckControl> checkControls = CheckSettingsPanel.Controls.OfType<CheckControl>();
+            foreach (CheckControl control in checkControls)
+                control.Hide();
+            Type type = (Type)CheckTypeComboBox.SelectedItem;
+            checkControl = checkControls.FirstOrDefault(c => c.CheckType == type);
+            if (checkControl == null)
+            {
+                checkControl = CheckControl.Create(type);
+                if (checkControl != null)
+                {
+                    checkControl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
+                    checkControl.Click += Control_Click;
+                    CheckSettingsPanel.Controls.Add(checkControl);
+                }
+            }
+            if (checkControl != null)
+            {
+                CheckSettingsPanel.Height = checkControl.Height;
+                //Height = 230 + checkControl.Height;
+                checkControl.Show();
+            }
+        }
+
+        private void LoadCheck(Check check)
+        {
+            NameTextBox.Text = Check.Name;
+            EnabledCheckBox.Checked = check.Enabled;
+            TimeoutInput.Value = check.Timeout;
+            FrequencyUnitsComboBox.SelectedItem = check.Schedule.Units;
+            FrequencyUpDown.Value = check.Schedule.Frequency;
+            StartTimePicker.Value = new DateTime(1970, 1, 1) + check.Schedule.StartTime;
+            EndTimePicker.Value = new DateTime(1970, 1, 1) + check.Schedule.EndTime;
+            checkControl?.LoadCheck(check);
+        }
+
+        private bool UpdateCheck(Check check, bool saving = true)
+        {
+            string result;
+            if (CheckTypeComboBox.SelectedIndex == -1)
+            {
+                result = "Check type cannot be blank.";
+            }
+            else
+            {
+                check.Id = CheckId;
+                check.Server = server;
+                check.Name = NameTextBox.Text;
+                check.Enabled = EnabledCheckBox.Checked;
+                check.Timeout = (int)TimeoutInput.Value;
+                check.Schedule = new Schedule((FrequencyUnits)FrequencyUnitsComboBox.SelectedItem, (int)FrequencyUpDown.Value, StartTimePicker.Value.TimeOfDay, EndTimePicker.Value.TimeOfDay);
+                checkControl?.UpdateCheck(check);
+                result = check.Validate(saving);
+            }
+            if (!result.IsNullOrEmpty())
+            {
+                MessageBox.Show(result, "Error validating check", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                return false;
+            }
+            return true;
+        }
+
+        private void OkButton_Click(object sender, EventArgs e)
+        {
+            if (!UpdateCheck(workCheck))
+                return;
+            Check = workCheck;
+            server.UpdateCheck(Check);
+            monitor.SaveServers();
+            Close();
+        }
+
+        private void CancelCheckButton_Click(object sender, EventArgs e)
+        {
+            Close();
+        }
+
+        private async void RunButton_Click(object sender, EventArgs e)
+        {
+            if (!UpdateCheck(workCheck, false))
+                return;
+
+            RunButton.Enabled = false;
+            RunButton.Text = "Running";
+            ResultLabel.Visible = ResultIconPictureBox.Visible = false;
+            CancelRunButton.Visible = true;
+
+            // Create a CancellationTokenSource for this execution, and set it to both variables.
+            // localCancellationTokenSource will mantain a reference to the token for this execution,
+            // while cancellationTokenSource might end up referencing a different token if the Cancel
+            // button is clicked (but the Task itself is unable to be cancelled), then Run is clicked
+            // again.
+            CancellationTokenSource localCancellationTokenSource = new CancellationTokenSource();
+            cancellationTokenSource = localCancellationTokenSource;
+            CheckResult result = await workCheck.ExecuteAsync(cancellationTokenSource.Token, false);
+            if (!localCancellationTokenSource.IsCancellationRequested)
+                OnRunFinished(result);
+            localCancellationTokenSource.Dispose();
+            localCancellationTokenSource = null;
+        }
+
+        //private void RunButton_Click(object sender, EventArgs e)
+        //{
+        //    if (!Check.Server.SshClient.IsConnected)
+        //        Check.Server.SshClient.Connect();
+        //    using (Renci.SshNet.SshCommand command = Check.Server.SshClient.CreateCommand("ls"))
+        //    {
+        //        //token.Register(command.CancelAsync);
+        //        //command.BeginExecute(asyncResult =>
+        //        //{
+        //        //    string result = command.EndExecute(asyncResult);
+        //        //    //tcs.SetResult(new CheckResult(this, CheckStatus.Success, result));
+        //        //});
+        //        IAsyncResult iar = command.BeginExecute(z);
+        //        command.EndExecute(iar);
+        //        //string result = command.Execute();
+        //        //System.Console.Write(result);
+        //    }
+        //}
+
+        //private void z(IAsyncResult ar)
+        //{
+        //    throw new NotImplementedException();
+        //}
+
+        private void CancelRunButton_Click(object sender, EventArgs e)
+        {
+            cancellationTokenSource.Cancel();
+            OnRunFinished();
+        }
+
+        /// <summary>Updates the UI after a check is finished running.</summary>
+        /// <param name="result">Result of the check execution. If null, the check was cancelled before it completed.</param>
+        private void OnRunFinished(CheckResult result = null)
+        {
+            RunButton.Enabled = true;
+            RunButton.Text = "Run";
+            CancelRunButton.Visible = false;
+            if (result != null)
+            {
+                ResultLabel.Text = result.Message;
+                //ResultLabel.ForeColor = result.CheckStatus == CheckStatus.Success ? Color.Green : Color.Red;
+                ResultIconPictureBox.Image = result.CheckStatus.GetIcon();
+                ResultLabel.Visible = ResultIconPictureBox.Visible = true;
+            }
+        }
+
+        /*private class CheckInfo
+        {
+            public GroupBox GroupBox { get; private set; }
+
+            public Func<string> ValidateFunction { get; private set; }
+
+            public CheckInfo(GroupBox groupBox, Func<string> validateFunction)
+            {
+                GroupBox = groupBox;
+                ValidateFunction = validateFunction;
+            }
+        }*/
+
+        private string BuildHelpText()
+        {
+            StringBuilder rtf = new StringBuilder(@"{\rtf1\ansi ");
+            foreach (Type checkType in Check.CheckTypes)
+            {
+                // Arguments to AppendLine() must end with a \ for the RichTextBox to render the newline character
+                rtf.Append(@"\b ").Append(Helpers.GetDisplayName(checkType)).AppendLine(@"\b0 \")
+                    .Append(checkType.GetAttribute<DescriptionAttribute>()?.Description ?? "No description provided.").AppendLine(@"\").AppendLine(@"\");
+            }
+            return rtf.ToString().TrimEnd(' ', '\r', '\n', '\\');
+        }
+
+        private void TypeHelpPictureBox_Click(object sender, EventArgs e)
+        {
+            if (helpShown)
+            {
+                helpForm.Close();
+            }
+            else
+            {
+                helpForm = new QuickHelpForm(BuildHelpText());
+                helpForm.FormClosed += QuickHelpForm_FormClosed;
+                helpForm.Show(this);
+                Activate();
+                helpShown = true;
+                OnHelpLocationChanged();
+            }
+        }
+
+        private void QuickHelpForm_FormClosed(object sender, FormClosedEventArgs e)
+        {
+            helpShown = false;
+            helpForm.FormClosed -= QuickHelpForm_FormClosed;
+            helpForm.Dispose();
+        }
+
+        private void OnHelpLocationChanged()
+        {
+            HelpLocationChanged?.Invoke(this, new HelpLocationChangedEventArgs(HelpLocation));
+        }
+
+        private void CheckTypePanel_LocationChanged(object sender, EventArgs e)
+        {
+            OnHelpLocationChanged();
+        }
+
+        private void CheckForm_Move(object sender, EventArgs e)
+        {
+            OnHelpLocationChanged();
+        }
+
+        private void Control_Click(object sender, EventArgs e)
+        {
+            if (helpShown)
+                helpForm.Close();
+        }
+
+        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+        {
+            if (keyData == Keys.Escape && helpShown)
+            {
+                helpForm.Close();
+                return true;
+            }
+            return base.ProcessCmdKey(ref msg, keyData);
+        }
+
+        private void FrequencyUnitsComboBox_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            ScheduleBetweenPanel.Visible = !(ScheduleAtPanel.Visible = FrequencyUnitsComboBox.SelectedIndex == 3);
+        }
+
+        private void FrequencyUnitsComboBox_Format(object sender, ListControlConvertEventArgs e)
+        {
+            e.Value = e.Value.ToString().ToLower() + 's';
+        }
+    }
+
+    public class HelpLocationChangedEventArgs : EventArgs
+    {
+        public Point HelpLocation { get; private set; }
+
+        public HelpLocationChangedEventArgs(Point helpLocation)
+        {
+            HelpLocation = helpLocation;
+        }
+    }
+}