Mercurial > servermonitor
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; + } + } +}