/* * 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. */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using ThoughtWorks.CruiseControl.Remote.Monitor; using ThoughtWorks.CruiseControl.Remote.Parameters; using ThoughtWorks.CruiseControl.Remote; using System.Threading; using FastForward.WinCore; namespace FastForward.Monitor { public partial class BuildParametersForm : Form { #region Private fields private Dictionary> parameters; private List controls = new List(); private MainForm owner; #endregion #region Constructors /// /// Initialise a new . /// /// public BuildParametersForm(Dictionary> parameters, MainForm owner) { InitializeComponent(); this.parameters = parameters; this.owner = owner; this.Owner = owner; // Load each project foreach (var project in parameters) { if (project.Value.Count() > 0) { // Add the project label var newLabel = new Label { Text = string.Format("Parameters for {0}", project.Key.Name), TextAlign = ContentAlignment.MiddleLeft, Dock = DockStyle.Fill, AutoSize = false, Font = new Font(parametersTable.Font, FontStyle.Bold | FontStyle.Underline), AutoEllipsis = true }; AddNewRow(newLabel, null); // Add each parameter foreach (var parameter in project.Value) { var itemLabel = new Label { Text = string.Format("{0}:", string.IsNullOrEmpty(parameter.DisplayName) ? parameter.Name : parameter.DisplayName), TextAlign = ContentAlignment.MiddleLeft, Dock = DockStyle.Fill, AutoSize = false, AutoEllipsis = true }; Control itemValue = null; var projectParameter = new ProjectParameter { Parameter = parameter, Project = project.Key }; if ((parameter.AllowedValues != null) && (parameter.AllowedValues.Length > 0)) { var combo = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Dock = DockStyle.Fill }; combo.Items.AddRange(parameter.AllowedValues); for (var loop = 0; loop < combo.Items.Count; loop++) { if (parameter.AllowedValues[loop] == parameter.ClientDefaultValue) { combo.SelectedIndex = loop; break; } } itemValue = combo; projectParameter.ValueGetter = (o) => { return (o as ComboBox).Text; }; } else { if (parameter.DataType == typeof(string)) { var textInput = new TextBox { Text = parameter.ClientDefaultValue }; var text = parameter as TextParameter; if (text != null) { textInput.MaxLength = text.MaximumLength; } itemValue = textInput; projectParameter.ValueGetter = (o) => { return (o as TextBox).Text; }; } else if ((parameter.DataType == typeof(int)) || (parameter.DataType == typeof(double))) { var numericInput = new NumericUpDown(); if (!string.IsNullOrEmpty(parameter.ClientDefaultValue)) { numericInput.Value = Convert.ToDecimal(parameter.DefaultValue); } var numeric = parameter as NumericParameter; if (numeric != null) { numericInput.Minimum = Convert.ToDecimal(numeric.MinimumValue); numericInput.Maximum = Convert.ToDecimal(numeric.MaximumValue); } itemValue = numericInput; projectParameter.ValueGetter = (o) => { return (o as NumericUpDown).Text; }; } else if (parameter.DataType == typeof(DateTime)) { var dateInput = new DateTimePicker(); if (!string.IsNullOrEmpty(parameter.DefaultValue)) { dateInput.Value = DateTime.Parse(parameter.ClientDefaultValue); } var date = parameter as DateParameter; if (date != null) { dateInput.MinDate = date.MinimumValue; dateInput.MaxDate = date.MaximumValue; } itemValue = dateInput; projectParameter.ValueGetter = (o) => { return (o as DateTimePicker).Text; }; } else { itemValue = new Label { Text = "Unknown data type: " + parameter.DataType.ToString(), TextAlign = ContentAlignment.MiddleLeft, AutoSize = false, AutoEllipsis = true }; } } itemValue.Tag = projectParameter; itemValue.Dock = DockStyle.Fill; itemValue.Margin = new Padding(0, 0, 20, 0); if (!string.IsNullOrEmpty(parameter.Description)) { itemTooltip.SetToolTip(itemLabel, parameter.Description); itemTooltip.SetToolTip(itemValue, parameter.Description); } itemValue.Enter += (o, e) => { var itemParameter = (o as Control).Tag as ProjectParameter; description.Text = itemParameter.Parameter.Description ?? string.Empty; }; AddNewRow(itemLabel, itemValue); controls.Add(itemValue); } } } } #endregion #region Private methods #region AddNewRow() /// /// Adds a new row. /// /// /// private void AddNewRow(Control label, Control value) { // Add the new row if (parametersTable.GetControlFromPosition(0, 0) != null) { parametersTable.RowCount += 1; parametersTable.RowStyles.Add(new RowStyle(SizeType.Absolute, 24)); } // Add the controls parametersTable.Controls.Add(label, 0, parametersTable.RowCount - 1); if (value == null) { parametersTable.SetColumnSpan(label, 2); } else { parametersTable.Controls.Add(value, 1, parametersTable.RowCount - 1); } } #endregion #endregion #region Event handlers #region okButton_Click() /// /// Send all the build requests. /// /// /// private void okButton_Click(object sender, EventArgs e) { var isValid = true; var values = new Dictionary>(); foreach (var control in controls) { var project = control.Tag as ProjectParameter; var parameter = project.Parameter; var value = project.GetValue(control); var errors = parameter.Validate(value); if (errors.Length > 0) { isValid = false; var messages = from error in errors select error.Message; errorProvider.SetError(control, string.Join(Environment.NewLine, messages.ToArray())); } else { errorProvider.SetError(control, null); var projectValues = new List(); if (values.ContainsKey(project.Project)) { projectValues = values[project.Project]; } else { values.Add(project.Project, projectValues); } projectValues.Add(new NameValuePair(parameter.Name, value)); } } if (isValid) { foreach (var project in parameters.Keys) { using (Trace.Start("Sending force build to " + project.Name)) { SendRequest((p, a) => p.ForceBuild(a), project, values.ContainsKey(project) ? values[project] : null); } } owner.DisplayStatus("Force build sent to {0} {1}", parameters.Count(), "project", "projects"); Close(); } } #endregion #region SendRequest() /// /// Pool a request for a remote server to process. /// /// /// /// private void SendRequest(Action> request, Project project, List parameters) { ThreadPool.QueueUserWorkItem(o => { try { request(project, parameters); } catch (Exception error) { owner.LogErrorMessage(project.Name, error.Message); } }); } #endregion #endregion #region Private classes #region ProjectParameter private class ProjectParameter { public Project Project { get; set; } public ParameterBase Parameter { get; set; } public Func ValueGetter { get; set; } public string GetValue(Control value) { if (ValueGetter == null) { return null; } else { return ValueGetter(value); } } } #endregion #endregion } }