/* * Copyright (c) 2009 Craig Sutherland * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ namespace FastForward.Monitor { using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows.Forms; using FastForward.WinCore; using FastForward.WinCore.Configuration; using Microsoft.Win32; using ThoughtWorks.CruiseControl.Remote; using ThoughtWorks.CruiseControl.Remote.Monitor; /// /// Display the settings for the monitor application. /// public partial class SettingsForm : Form { #region Private fields private Dictionary plugins = new Dictionary(); private Dictionary tabItems = new Dictionary(); private string[] allProjectDoubleClickActions = new string[] { "(None)", "View Build History", "View Current Status", "View Packages", "View Properties", "View Web Page" }; #endregion #region Constructors /// /// Initialise a new . /// /// public SettingsForm(ApplicationConfig configuration) { InitializeComponent(); var clientfactory = new CruiseServerClientFactory(); Configuration = configuration.Clone(); var settings = new ClientStartUpSettings { FetchVersionOnStartUp = false }; foreach (var server in Configuration.Servers) { // Need to make sure there is a server instance for each item var client = clientfactory.GenerateClient(server.Address, server.TargetServer); server.Server = new Server(client, settings); server.Server.DisplayName = server.Name; // Now it can be added to the listview serversList.Items.Add(new ServerConfigItem(server)); } foreach (var template in Configuration.BuildTemplates) { templateList.Items.Add( new ListViewItem( new string[] { template.Name, template.FileName }, "Template")); } foreach (var plugin in Configuration.LoadedPlugins) { ListViewItem item; try { item = GeneratePluginItem(plugin); plugins.Add(plugin, Plugin.StartNew(plugin)); } catch { item = new ListViewItem(new string[] { plugin.Type, "Unable to load plug-in!" }, "Error"); item.Tag = plugin; } pluginsList.Items.Add(item); } foreach (var tab in from record in Configuration.Monitor.Tabs orderby record.Order select record) { AddTabToList(tab); } // Settings showInTaskBar.Checked = Configuration.Monitor.ShowInTaskBar; alwaysOnTop.Checked = Configuration.Monitor.AlwaysOnTop; pluginLocation.Text = Configuration.DefaultPluginLocation; // Load the all projecs double-click action allProjectsDoubleClickAction.Items.Clear(); for (var loop = 0; loop < allProjectDoubleClickActions.Length; loop++) { var action = allProjectDoubleClickActions[loop]; allProjectsDoubleClickAction.Items.Add(action); if (string.Equals(action, this.Configuration.Monitor.AllProjectsDoubleClickAction)) { allProjectsDoubleClickAction.SelectedIndex = loop; } } if (allProjectsDoubleClickAction.SelectedIndex < 0) { allProjectsDoubleClickAction.SelectedIndex = 0; } // Windows only functionality if (EnvironmentUtils.IsRunningOnWindows) { startAutomatically.Checked = CheckForAutoRun(); } else { startAutomatically.Visible = false; } } #endregion #region Public properties #region Configuration /// /// The current configuration. /// public ApplicationConfig Configuration { get; private set; } #endregion #endregion #region Public events #region OkClicked /// /// The OK button has been clicked. /// public event EventHandler OkClicked; #endregion #endregion #region Private methods #region CheckForAutoRun() /// /// Checks if this application has been set to run when Windows is started. /// /// private bool CheckForAutoRun() { var hasAutoRun = false; var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", false); if (regKey != null) { hasAutoRun = !string.IsNullOrEmpty((string)regKey.GetValue("FastForward.Monitor")); } return hasAutoRun; } #endregion #region SetAutoRun() /// /// Sets whether this application should start when Windows starts. /// /// private void SetAutoRun(bool hasAutoRun) { var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); if (regKey != null) { if (hasAutoRun) { regKey.SetValue("FastForward.Monitor", System.Windows.Forms.Application.ExecutablePath); } else { regKey.DeleteValue("FastForward.Monitor", false); } } } #endregion #region ShowProjectsForServer() /// /// Display the projects that are available for a server. /// private void ShowProjectsForServer() { if (serversList.SelectedItems.Count == 1) { var item = serversList.SelectedItems[0] as ServerConfigItem; var form = new ServerProjectsForm(item.Server); form.ShowDialog(this); } else { MessageBox.Show(this, "You must select a server first", "Unable to configure server", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region GeneratePluginItem() /// /// Generates a for a plugin configuration. /// /// /// private ListViewItem GeneratePluginItem(PluginConfig config) { // Retrieve the name and description var type = Plugin.RetrieveType(config); var name = Plugin.RetrieveName(type); var description = Plugin.RetrieveDescription(type); // Generate the actual item var item = new ListViewItem(new string[] { name, description }, "Plugin"); item.Tag = config; return item; } #endregion #region AddTabToList() /// /// Adds a tab to the list. /// /// private void AddTabToList(TabConfig tab) { var item = new ListViewItem(new string[] { tab.Text, tab.Type.ToString() }, "Tabs"); item.Tag = tab; tabsList.Items.Add(item); tabItems.Add(tab.Key, item); } #endregion #region MoveTab() /// /// Moves a tab. /// /// The direction to move. private void MoveTab(int direction) { var currentIndex = tabsList.SelectedItems[0].Index; var currentTab = tabsList.SelectedItems[0].Tag as TabConfig; if (((direction == 1) && (currentIndex < (tabsList.Items.Count - 1))) || (direction == -1) && (currentIndex > 0)) { var oldTab = tabsList.Items[currentIndex + direction]; (oldTab.Tag as TabConfig).Order -= direction; currentTab.Order += direction; oldTab.Remove(); tabsList.Items.Insert(currentIndex, oldTab); } } #endregion #endregion #region Event handlers #region addButton_Click() /// /// The user has clicked on the Add server button. /// /// /// private void addButton_Click(object sender, EventArgs e) { var addForm = new AddServerForm((from serverItem in Configuration.Servers select serverItem.Address.ToLower()).ToList()); ServerConfig server = null; addForm.OkClicked += (o, a) => { server = new ServerConfig { Address = addForm.ServerAddress, Settings = addForm.Settings, TargetServer = addForm.TargetServer, TransportMode = addForm.TransportMode, Version = addForm.ServerVersion, Server = new Server(addForm.Client) }; Configuration.Servers.Add(server); serversList.Items.Add(new ServerConfigItem(server)); }; var result = addForm.ShowDialog(this); if (result == DialogResult.OK) { var configForm = new ServerConfigurationForm(server); configForm.ShowDialog(this); } } #endregion #region okButton_Click() /// /// The user has clicked the ok button. /// /// /// private void okButton_Click(object sender, EventArgs e) { Configuration.Monitor.ShowInTaskBar = showInTaskBar.Checked; Configuration.Monitor.AlwaysOnTop = alwaysOnTop.Checked; Configuration.DefaultPluginLocation = pluginLocation.Text; var action = allProjectsDoubleClickAction.SelectedItem.ToString(); Configuration.Monitor.AllProjectsDoubleClickAction = (action == allProjectDoubleClickActions[0]) ? string.Empty : action; // Windows only functionality if (EnvironmentUtils.IsRunningOnWindows) { SetAutoRun(startAutomatically.Checked); } if (OkClicked != null) OkClicked(this, EventArgs.Empty); DialogResult = DialogResult.OK; Close(); } #endregion #region configureButton_Click() /// /// The user has clicked on the configure server button. /// /// /// private void configureButton_Click(object sender, EventArgs e) { if (serversList.SelectedItems.Count == 1) { var item = serversList.SelectedItems[0] as ServerConfigItem; var configForm = new ServerConfigurationForm(item.Server); if (configForm.ShowDialog(this) == DialogResult.OK) { item.Server.Server.DisplayName = item.Server.Name; } } else { MessageBox.Show(this, "You must select a server first", "Unable to configure server", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region removeButton_Click() /// /// The user has clicked on the remove server button. /// /// /// private void removeButton_Click(object sender, EventArgs e) { if (serversList.SelectedItems.Count == 1) { var item = serversList.SelectedItems[0] as ServerConfigItem; if (MessageBox.Show(this, string.Format("Are you sure you want to remove the server '{0}'?", item.Server.Server.GetDisplayName(true)), "Remove server", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { Configuration.Servers.Remove(item.Server); item.Remove(); } } else { MessageBox.Show(this, "You must select a server first", "Unable to remove server", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region serversList_DoubleClick() /// /// The user has double-clicked on a server in the servers list view. /// /// /// private void serversList_DoubleClick(object sender, EventArgs e) { ShowProjectsForServer(); } #endregion #region projectsButton_Click() /// /// The user has clicked on the projects button. /// /// /// private void projectsButton_Click(object sender, EventArgs e) { ShowProjectsForServer(); } #endregion #region addTemplateButton_Click() /// /// The user has clicked on the add template button. /// /// /// private void addTemplateButton_Click(object sender, EventArgs e) { var addForm = new AddTemplateForm(Configuration); addForm.OkClicked += (o, a) => { Configuration.BuildTemplates.Add(addForm.Configuration); templateList.Items.Add( new ListViewItem( new string[] { addForm.Configuration.Name, addForm.Configuration.FileName }, "Template")); }; addForm.ShowDialog(this); } #endregion #region removeTemplateButton_Click() /// /// The user has clicked on the remove template button. /// /// /// private void removeTemplateButton_Click(object sender, EventArgs e) { if (templateList.SelectedItems.Count == 1) { var item = templateList.SelectedItems[0]; if (MessageBox.Show(this, string.Format("Are you sure you want to remove the template '{0}'?", item.Text), "Remove template", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { var config = (from record in Configuration.BuildTemplates where record.Name == item.Text select record).Single(); ; Configuration.BuildTemplates.Remove(config); item.Remove(); } } else { MessageBox.Show(this, "You must select a template first", "Unable to remove template", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region addPluginButton_Click() /// /// Add a new plugin /// /// /// private void addPluginButton_Click(object sender, EventArgs e) { var pluginForm = new AddPluginForm(Configuration.LoadedPlugins, Configuration.DefaultPluginLocation); pluginForm.OkClicked += (o, a) => { var plugin = PluginConfig.StartNew(pluginForm.SelectedPlugin); var item = GeneratePluginItem(plugin); pluginsList.Items.Add(item); var actualPlugin = Plugin.StartNew(plugin); plugins.Add(plugin, actualPlugin); Configuration.LoadedPlugins.Add(plugin); var lastTab = Configuration.Monitor.Tabs.Max(t => t.Order); foreach (var tab in actualPlugin.ListTabs()) { var tabConfig = new TabConfig { Key = plugin.Key + ":" + tab, Order = ++lastTab, Text = tab, Type = TabConfigType.Plugin }; Configuration.Monitor.Tabs.Add(tabConfig); AddTabToList(tabConfig); } }; pluginForm.ShowDialog(this); } #endregion #region removePluginButton_Click() /// /// Remove a plugin. /// /// /// private void removePluginButton_Click(object sender, EventArgs e) { if (pluginsList.SelectedItems.Count == 1) { var item = pluginsList.SelectedItems[0]; if (MessageBox.Show(this, string.Format("Are you sure you want to remove the plugin '{0}'?", item.Text), "Remove plugin", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { var config = Configuration.FindPlugin((item.Tag as PluginConfig).Key); Configuration.LoadedPlugins.Remove(config); item.Remove(); var configTag = item.Tag as PluginConfig; if ((configTag != null) && plugins.ContainsKey(configTag)) { plugins.Remove(configTag); } // Remove any associated tabs var tabs = (from record in Configuration.Monitor.Tabs where record.Key.StartsWith(config.Key) select record).ToArray(); foreach (var tab in tabs) { Configuration.Monitor.Tabs.Remove(tab); tabItems[tab.Key].Remove(); tabItems.Remove(tab.Key); } } } else { MessageBox.Show(this, "You must select a plugin first", "Unable to remove plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region configurePluginButton_Click() /// /// Configure a plugin. /// /// /// private void configurePluginButton_Click(object sender, EventArgs e) { if (pluginsList.SelectedItems.Count == 1) { var item = pluginsList.SelectedItems[0]; var config = item.Tag as PluginConfig; if ((config != null) && plugins.ContainsKey(config)) { try { plugins[config].Configure(); config.Data = plugins[config].Configuration.Data; } catch (Exception error) { MessageBox.Show(this, "An unexpected error occurred while trying to configure this plugin: " + error.Message, "Unable to configure plugin", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { MessageBox.Show(this, "Unable to configure plugin - there was an error while loading the plugin", "Unable to configure plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } else { MessageBox.Show(this, "You must select a plugin first", "Unable to remove plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } #endregion #region advancedSettings_CheckedChanged() /// /// Show or hide the advanced settings. /// /// /// private void advancedSettings_CheckedChanged(object sender, EventArgs e) { advancedSettingsPanel.Visible = advancedSettings.Checked; } #endregion #region findPluginLocation_Click() /// /// The user wants to find the plug-in location. /// /// /// private void findPluginLocation_Click(object sender, EventArgs e) { var dialog = new FolderBrowserDialog { Description = "Find the default plug-in location.", SelectedPath = pluginLocation.Text, ShowNewFolderButton = true }; if (dialog.ShowDialog(this) == DialogResult.OK) { pluginLocation.Text = dialog.SelectedPath; } } #endregion #region moveUpButton_Click() /// /// Moves a tab up in the order. /// /// /// private void moveUpButton_Click(object sender, EventArgs e) { if (tabsList.SelectedItems.Count == 0) { MessageBox.Show("No tabs selected - unable to move", "Move up failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { MoveTab(-1); } } #endregion #region moveDownButton_Click() /// /// Moves a tab down in the order. /// /// /// private void moveDownButton_Click(object sender, EventArgs e) { if (tabsList.SelectedItems.Count == 0) { MessageBox.Show("No tabs selected - unable to move", "Move down failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { MoveTab(1); } } #endregion #region addTabButton_Click() /// /// Add a new tab. /// /// /// private void addTabButton_Click(object sender, EventArgs e) { MessageBox.Show("TODO: Add tab"); } #endregion #region removeTabButton_Click() /// /// Remove an existing tab/ /// /// /// private void removeTabButton_Click(object sender, EventArgs e) { if (tabsList.SelectedItems.Count == 0) { MessageBox.Show("No tabs selected - unable to remove", "Remove failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else if (tabsList.Items.Count == 1) { MessageBox.Show("Cannot remove last tab - at least one tab must be visible", "Remove failed", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { MessageBox.Show("TODO: Remove tab"); } } #endregion #endregion #region Private classes #region ServerConfigItem /// /// A that displays details on a server. /// private class ServerConfigItem : ListViewItem { #region Constructors /// /// Initialise a new . /// /// public ServerConfigItem(ServerConfig value) { Server = value; Text = value.Server.GetDisplayName(true); SubItems.Add(string.Empty); SetTransport(); value.Server.PropertyChanged += Server_PropertyChanged; } #endregion #region Public properties #region Server /// /// The server that is being displayed. /// public ServerConfig Server { get; set; } #endregion #endregion #region Private methods #region SetTransport() /// /// Display the transport - both the text and the image. /// private void SetTransport() { string transport = "(Default)"; string image = "DefaultTransport"; switch (Server.TransportMode) { case ServerTransportMode.Http: transport = "HTTP"; image = "HttpTransport"; break; case ServerTransportMode.Remoting: transport = ".NET Remoting"; image = "RemotingTransport"; break; case ServerTransportMode.TcpCache: transport = "FastForward.NET Cache (TCP)"; image = "FastForward"; break; } SubItems[1].Text = transport; ImageKey = image; } #endregion #region Server_PropertyChanged() private void Server_PropertyChanged(object sender, PropertyChangedEventArgs e) { Text = Server.Server.GetDisplayName(true); } #endregion #endregion } #endregion #endregion } }