using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Model;
using System.Linq;
namespace Kaleida.ServiceMonitor.UI
{
public partial class ScriptWorkspaceControl : UserControl
{
private ScriptWorkspace workspace = new ScriptWorkspace();
private bool suppressSelectedIndexChangedEvent;
private string scriptDirectoryPath;
public ScriptWorkspaceControl()
{
InitializeComponent();
cbScripts.SelectedIndexChanged += cbScripts_SelectedIndexChanged;
cbScripts.DisplayMember = "NameAndDirtyStatus";
scriptEditor.SaveRequested += (s, e) => SaveCurrentScript();
}
[NotNull]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ScriptWorkspace Workspace
{
get { return workspace; }
set
{
if (value == null) throw new ArgumentNullException("value");
workspace = value;
workspace.CurrentScriptChanged += CurrentScriptChanged;
workspace.CurrentScriptContentChanged += CurrentScriptContentChanged;
workspace.LoadedScriptListChanged += LoadedScriptListChangedHandler;
}
}
public string ScriptDirectoryPath
{
get { return scriptDirectoryPath; }
set { scriptDirectoryPath = value; }
}
public void CurrentScriptChanged(object sender, EventArgs e)
{
var currentScript = workspace.CurrentScript;
var selectedIndex = workspace.LoadedScripts.IndexOf(currentScript);
cbScripts.SelectedIndex = selectedIndex;
scriptEditor.Script = currentScript;
UpdateSaveButtonState();
}
public void CurrentScriptContentChanged(object sender, EventArgs e)
{
UpdateSaveButtonState();
cbScripts.Text = workspace.CurrentScript.GetNameAndEditState();
RefreshComboBoxInPlace();
}
public void LoadedScriptListChangedHandler(object sender, EventArgs e)
{
ReloadComboBoxAndReselect();
}
private void ReloadComboBoxAndReselect()
{
var selectedScriptName = workspace.CurrentScript.Name;
suppressSelectedIndexChangedEvent = true;
cbScripts.Items.Clear();
foreach (var script in workspace.LoadedScripts)
{
cbScripts.Items.Add(script.GetNameAndEditState());
}
suppressSelectedIndexChangedEvent = false;
TrySelectScript(selectedScriptName);
}
private void RefreshComboBoxInPlace()
{
suppressSelectedIndexChangedEvent = true;
for (int i = 0; i < workspace.LoadedScripts.Count; i++)
{
cbScripts.Items[i] = workspace.LoadedScripts[i].GetNameAndEditState();
}
suppressSelectedIndexChangedEvent = false;
}
public void TrySelectScript(string scriptName)
{
var matching = workspace.LoadedScripts.FirstOrDefault(i => string.Equals(i.Name, scriptName, StringComparison.OrdinalIgnoreCase));
workspace.CurrentScript = matching ?? workspace.LoadedScripts.FirstOrDefault() ?? new NullScriptSource();
}
private void cbScripts_SelectedIndexChanged(object sender, EventArgs e)
{
if (suppressSelectedIndexChangedEvent) return;
var isValidScriptIndex = cbScripts.SelectedIndex >= 0 && cbScripts.SelectedIndex < workspace.LoadedScripts.Count();
workspace.CurrentScript = isValidScriptIndex ? workspace.LoadedScripts[cbScripts.SelectedIndex] : new NullScriptSource();
scriptEditor.Script = workspace.CurrentScript;
UpdateSaveButtonState();
scriptEditor.Focus();
}
private void btnNewScript_Click(object sender, EventArgs e)
{
var dialog = new NewScriptDialog();
if (dialog.ShowDialog(this) == DialogResult.OK)
{
var newPath = Path.Combine(scriptDirectoryPath, dialog.ScriptName + ".mscr");
if (File.Exists(newPath))
{
MessageBox.Show(string.Format("A script already exists with the name '{0}'", dialog.ScriptName), "Cannot create new script", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
workspace.NewScript(newPath);
scriptEditor.Focus();
}
}
private void btnReload_Click(object sender, EventArgs e)
{
bool cancelled = AllowUserToSaveDirty();
if (!cancelled)
{
var selectedScriptName = workspace.CurrentScript.Name;
workspace.UnloadAllScripts();
LoadScriptsFromScriptsDirectory();
TrySelectScript(selectedScriptName);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
SaveCurrentScript();
}
public void LoadScriptsFromDisk()
{
LoadScriptsFromScriptsDirectory();
UpdateSaveButtonState();
}
private void LoadScriptsFromScriptsDirectory()
{
if (!Directory.Exists(scriptDirectoryPath))
throw new InvalidOperationException(string.Format("The required Scripts directory '{0}' does not exist", scriptDirectoryPath));
var scriptPaths = Directory.GetFiles(scriptDirectoryPath, "*.mscr", SearchOption.AllDirectories);
foreach(var scriptPath in scriptPaths)
{
workspace.LoadScript(scriptPath);
}
}
private void UpdateSaveButtonState()
{
btnSave.Enabled = !(workspace.CurrentScript is NullScriptSource) && workspace.CurrentScript.IsDirty;
}
private void SaveCurrentScript()
{
workspace.SaveCurrentScript();
UpdateSaveButtonState();
RefreshComboBoxInPlace();
}
public bool AllowUserToSaveDirty()
{
bool cancelled = false;
var unsavedScripts = workspace.LoadedScripts.Where(i => i.IsDirty);
foreach (var unsavedScript in unsavedScripts)
{
workspace.CurrentScript = unsavedScript;
var result = MessageBox.Show(string.Format("Save changes to '{0}'?", unsavedScript.Name), "Unsaved script", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Cancel)
{
cancelled = true;
break;
}
if (result == DialogResult.Yes)
{
SaveCurrentScript();
}
}
return cancelled;
}
private void ScriptWorkspaceControl_Resize(object sender, EventArgs e)
{
bool hasConstrainedHeight = Height < 100;
bool hasConstrainedWidth = Width < 360 ;
lblAvailableScripts.Visible = !hasConstrainedWidth && !hasConstrainedHeight;
cbScripts.Visible = !hasConstrainedHeight;
scriptEditor.Location = hasConstrainedHeight ? new Point(3, 8) : new Point(3, 29);
scriptEditor.Height = hasConstrainedHeight ? Height - 10 : Height - 29;
cbScripts.Location = hasConstrainedWidth ? new Point(8, 2) : new Point(97, 2);
cbScripts.Width = hasConstrainedWidth ? Width - 16 : Width - 274;
btnNewScript.Visible = !hasConstrainedWidth && !hasConstrainedHeight;
btnReload.Visible = !hasConstrainedWidth && !hasConstrainedHeight;
btnSave.Visible = !hasConstrainedWidth && !hasConstrainedHeight;
}
}
}