/*
* 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
}
}