diff --git a/Source/TeamBuildMonitorGadget.sln b/Source/TeamBuildMonitorGadget.sln new file mode 100644 index 0000000..c3ddaaf --- /dev/null +++ b/Source/TeamBuildMonitorGadget.sln @@ -0,0 +1,24 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamBuildMonitorGadget", "TeamBuildMonitorGadget\TeamBuildMonitorGadget.csproj", "{BA7022CF-10AD-4F4A-9C01-86E739B92318}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BA7022CF-10AD-4F4A-9C01-86E739B92318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA7022CF-10AD-4F4A-9C01-86E739B92318}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA7022CF-10AD-4F4A-9C01-86E739B92318}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA7022CF-10AD-4F4A-9C01-86E739B92318}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/TeamBuildMonitorGadget/App.xaml b/Source/TeamBuildMonitorGadget/App.xaml new file mode 100644 index 0000000..5a6a59e --- /dev/null +++ b/Source/TeamBuildMonitorGadget/App.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/Source/TeamBuildMonitorGadget/App.xaml.cs b/Source/TeamBuildMonitorGadget/App.xaml.cs new file mode 100644 index 0000000..9a92511 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/App.xaml.cs @@ -0,0 +1,16 @@ +using System; +using System.Windows; +using System.Windows.Navigation; +using System.Data; +using System.Xml; +using System.Configuration; + +namespace TeamBuildMonitorGadget { + /// + /// Interaction logic for App.xaml + /// + + public partial class App : System.Windows.Application { + + } +} \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/BuildStoreDriver.cs b/Source/TeamBuildMonitorGadget/BuildStoreDriver.cs new file mode 100644 index 0000000..033e0d4 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/BuildStoreDriver.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using Microsoft.TeamFoundation.Build.Proxy; +using System.ComponentModel; +using System.Windows.Documents; +using System.Collections.ObjectModel; +using Microsoft.TeamFoundation.Client; +using System.Net; +using Microsoft.TeamFoundation.Build.Common; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class BuildStoreDriver : DependencyObject { + private BuildStoreWorker _backgroundWorker; + + public BuildStoreDriver() { + + } + + public static readonly DependencyProperty TeamFoundationServerUriProperty = DependencyProperty.Register("TeamFoundationServerUri", typeof(string), typeof(BuildStoreDriver), new UIPropertyMetadata(null, RecreateBackgroundWorker)); + public static readonly DependencyProperty TeamProjectNameProperty = DependencyProperty.Register("TeamProjectName", typeof(string), typeof(BuildStoreDriver), new UIPropertyMetadata(null, RecreateBackgroundWorker)); + public static readonly DependencyProperty TeamBuildTypeNameProperty = DependencyProperty.Register("TeamBuildTypeName", typeof(string), typeof(BuildStoreDriver), new UIPropertyMetadata(null, RecreateBackgroundWorker)); + public static readonly DependencyProperty IsUpdatingProperty = DependencyProperty.Register("IsUpdating", typeof(bool), typeof(BuildStoreDriver), new UIPropertyMetadata(false)); + public static readonly DependencyProperty LastExceptionProperty = DependencyProperty.Register("LastException", typeof(Exception), typeof(BuildStoreDriver), new UIPropertyMetadata(null)); + private static readonly DependencyPropertyKey PreviousBuildsPropertyKey = DependencyProperty.RegisterReadOnly("PreviousBuilds", typeof(ObservableCollection), typeof(BuildStoreDriver), new UIPropertyMetadata(null)); + public static readonly DependencyProperty PreviousBuildsProperty = PreviousBuildsPropertyKey.DependencyProperty; + + public ObservableCollection PreviousBuilds { + get { return (ObservableCollection)GetValue(PreviousBuildsProperty); } + private set { SetValue(PreviousBuildsPropertyKey, value); } + } + + public string TeamFoundationServerUri { + get { return (string)GetValue(TeamFoundationServerUriProperty); } + set { SetValue(TeamFoundationServerUriProperty, value); } + } + + public string TeamProjectName { + get { return (string)GetValue(TeamProjectNameProperty); } + set { SetValue(TeamProjectNameProperty, value); } + } + + public string TeamBuildTypeName { + get { return (string)GetValue(TeamBuildTypeNameProperty); } + set { SetValue(TeamBuildTypeNameProperty, value); } + } + + public Exception LastException { + get { return (Exception)GetValue(LastExceptionProperty); } + set { SetValue(LastExceptionProperty, value); } + } + + private static void RecreateBackgroundWorker(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { + BuildStoreDriver driver = dependencyObject as BuildStoreDriver; + if (driver != null) { + driver.PreviousBuilds = new ObservableCollection(); + if (driver._backgroundWorker != null) { + driver._backgroundWorker.CancelAsync(); + } + driver._backgroundWorker = new BuildStoreWorker(driver.TeamFoundationServerUri, driver.TeamProjectName, driver.TeamBuildTypeName, driver.PreviousBuilds); + driver._backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( + delegate(object sender, RunWorkerCompletedEventArgs workedCompletedEventArgs) { + if (workedCompletedEventArgs.Error != null) { + driver.LastException = workedCompletedEventArgs.Error; + } + }); + } + } + + public void Monitor() { + VerifyAccess(); + + if (!_backgroundWorker.IsBusy) { + this.LastException = null; + _backgroundWorker.RunWorkerAsync(); + } + } + } +} diff --git a/Source/TeamBuildMonitorGadget/BuildStoreWorker.cs b/Source/TeamBuildMonitorGadget/BuildStoreWorker.cs new file mode 100644 index 0000000..b5750c8 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/BuildStoreWorker.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using Microsoft.TeamFoundation.Client; +using Microsoft.TeamFoundation.Build.Proxy; +using System.Collections.ObjectModel; +using System.Net; +using System.Threading; +using System.Windows; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class BuildStoreWorker : BackgroundWorker { + private string _teamFoundationServerUri; + private string _teamProjectName; + private string _teamBuildTypeName; + private BuildSummaryFactory _summaryFactory; + private ObservableCollection _buildSummaries; + + public BuildStoreWorker(string teamFoundationServerUri, string teamProjectName, string teamBuildTypeName, ObservableCollection buildSummaries) { + _teamFoundationServerUri = teamFoundationServerUri; + _teamProjectName = teamProjectName; + _teamBuildTypeName = teamBuildTypeName; + _buildSummaries = buildSummaries; + _summaryFactory = new BuildSummaryFactory(); + + this.WorkerSupportsCancellation = true; + this.WorkerReportsProgress = true; + this.DoWork += new DoWorkEventHandler(BuildStoreWorker_DoWork); + this.ProgressChanged += new ProgressChangedEventHandler(BuildStoreWorker_ProgressChanged); + } + + private void BuildStoreWorker_DoWork(object sender, DoWorkEventArgs e) { + + TeamFoundationServer server = new TeamFoundationServer(_teamFoundationServerUri, CredentialCache.DefaultCredentials); + server.EnsureAuthenticated(); + + while (!this.CancellationPending) { + BuildStore store = (BuildStore)server.GetService(typeof(BuildStore)); + BuildData[] builds = store.GetListOfBuilds(_teamProjectName, _teamBuildTypeName); + this.ReportProgress(0, builds); + Thread.Sleep(30000); + } + } + + private void BuildStoreWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { + BuildData[] results = (BuildData[])e.UserState; + + List summaries = new List(); + foreach (BuildData buildData in results) { + BuildSummary summary = _summaryFactory.GetBuildSummary(buildData); + summaries.Add(summary); + } + summaries.Sort(); + + _buildSummaries.Clear(); + for (int i = 0; i < summaries.Count && i < 4; i++) { + _buildSummaries.Add(summaries[i]); + } + + } + } +} diff --git a/Source/TeamBuildMonitorGadget/BuildSummary.cs b/Source/TeamBuildMonitorGadget/BuildSummary.cs new file mode 100644 index 0000000..a232d0c --- /dev/null +++ b/Source/TeamBuildMonitorGadget/BuildSummary.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class BuildSummary : INotifyPropertyChanged, IComparable { + private string _buildNumber; + private DateTime _buildDate; + private string _buildStatus; + private string _buildUri; + private string _dropLocation; + + public static readonly PropertyChangedEventArgs BuildNumberPropertyChangedEventArgs = new PropertyChangedEventArgs("BuildNumber"); + public static readonly PropertyChangedEventArgs BuildDatePropertyChangedEventArgs = new PropertyChangedEventArgs("BuildDate"); + public static readonly PropertyChangedEventArgs BuildStatusPropertyChangedEventArgs = new PropertyChangedEventArgs("BuildStatus"); + public static readonly PropertyChangedEventArgs DropLocationPropertyChangedEventArgs = new PropertyChangedEventArgs("DropLocation"); + + public string BuildUri { + get { return _buildUri; } + internal set { _buildUri = value; } + } + + public string BuildNumber { + get { return _buildNumber; } + set { + _buildNumber = value; + OnPropertyChanged(BuildNumberPropertyChangedEventArgs); + } + } + + public DateTime BuildDate { + get { return _buildDate; } + set { + _buildDate = value; + OnPropertyChanged(BuildDatePropertyChangedEventArgs); + } + } + + public string BuildStatus { + get { return _buildStatus; } + set { + _buildStatus = value; + OnPropertyChanged(BuildStatusPropertyChangedEventArgs); + } + } + + public string DropLocation { + get { return _dropLocation; } + set { + _dropLocation = value; + OnPropertyChanged(DropLocationPropertyChangedEventArgs); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { + if (this.PropertyChanged != null) { + this.PropertyChanged(this, e); + } + } + + #region IComparable Members + + public int CompareTo(BuildSummary other) { + return other.BuildDate.CompareTo(this.BuildDate); + } + + #endregion + } +} diff --git a/Source/TeamBuildMonitorGadget/BuildSummaryFactory.cs b/Source/TeamBuildMonitorGadget/BuildSummaryFactory.cs new file mode 100644 index 0000000..9131ba0 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/BuildSummaryFactory.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.TeamFoundation.Build.Proxy; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class BuildSummaryFactory { + private List _summaries = new List(); + + public BuildSummary GetBuildSummary(BuildData buildData) { + BuildSummary result = null; + + foreach (BuildSummary summary in _summaries) { + if (summary.BuildUri == buildData.BuildUri) { + result = summary; + break; + } + } + + if (result == null) { + result = new BuildSummary(); + _summaries.Add(result); + } + + result.BuildDate = buildData.StartTime; + result.BuildNumber = buildData.BuildNumber; + result.BuildStatus = buildData.BuildStatus; + result.BuildUri = buildData.BuildUri; + result.DropLocation = buildData.DropLocation; + + return result; + } + } +} diff --git a/Source/TeamBuildMonitorGadget/DateConverter.cs b/Source/TeamBuildMonitorGadget/DateConverter.cs new file mode 100644 index 0000000..6a692c6 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/DateConverter.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Data; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class DateConverter : IValueConverter { + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + string result = string.Empty; + + if (value != null) { + DateTime dt = (DateTime)value; + if (parameter != null) { + if (parameter.ToString() == "today") { + if (dt.Date == DateTime.Today) { + result = "Today"; + } else if (dt.Date == DateTime.Today.AddDays(-1)) { + result = "Yesterday"; + } else { + result = dt.ToString("dd-MMM"); + } + } else { + result = dt.ToString(parameter.ToString()); + } + } else { + result = dt.ToString("dd-MMM"); + } + } + + return result; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + throw new Exception("The method or operation is not implemented."); + } + } +} diff --git a/Source/TeamBuildMonitorGadget/Gadget.html b/Source/TeamBuildMonitorGadget/Gadget.html new file mode 100644 index 0000000..cf46751 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Gadget.html @@ -0,0 +1,24 @@ + + + Team Build Monitor Gadget + + + + + + + \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/Gadget.xml b/Source/TeamBuildMonitorGadget/Gadget.xml new file mode 100644 index 0000000..ce38cd5 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Gadget.xml @@ -0,0 +1,21 @@ + + + Team Build Monitor + PaulStovell.TeamBuildMonitorGadget + 1.0.0.0 + + + + 2007 + Team Build Monitor + + + + + + + full + + + + diff --git a/Source/TeamBuildMonitorGadget/GadgetBackground.png b/Source/TeamBuildMonitorGadget/GadgetBackground.png new file mode 100644 index 0000000..c5e0fc2 Binary files /dev/null and b/Source/TeamBuildMonitorGadget/GadgetBackground.png differ diff --git a/Source/TeamBuildMonitorGadget/GadgetIcon.gif b/Source/TeamBuildMonitorGadget/GadgetIcon.gif new file mode 100644 index 0000000..a35c345 Binary files /dev/null and b/Source/TeamBuildMonitorGadget/GadgetIcon.gif differ diff --git a/Source/TeamBuildMonitorGadget/IsNullVisibilityConverter.cs b/Source/TeamBuildMonitorGadget/IsNullVisibilityConverter.cs new file mode 100644 index 0000000..35eb078 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/IsNullVisibilityConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Data; +using System.Windows; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class IsNullVisibilityConverter : IValueConverter { + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + Visibility result = Visibility.Visible; + + if (parameter == null) { + result = (value == null) ? Visibility.Visible : Visibility.Collapsed; + } else if (parameter.ToString().ToLower().Contains("not")) { + result = (value == null) ? Visibility.Collapsed : Visibility.Visible; + } + + return result; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + throw new Exception("The method or operation is not implemented."); + } + } +} diff --git a/Source/TeamBuildMonitorGadget/MainPage.xaml b/Source/TeamBuildMonitorGadget/MainPage.xaml new file mode 100644 index 0000000..cd9535d --- /dev/null +++ b/Source/TeamBuildMonitorGadget/MainPage.xaml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Settings + + + + + + + + + + + There was an error communicating with the server. + View details + | + Try again + + + + + diff --git a/Source/TeamBuildMonitorGadget/MainPage.xaml.cs b/Source/TeamBuildMonitorGadget/MainPage.xaml.cs new file mode 100644 index 0000000..2af120f --- /dev/null +++ b/Source/TeamBuildMonitorGadget/MainPage.xaml.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Timers; +using System.Diagnostics; +using Microsoft.TeamFoundation.VersionControl.Client; + +namespace PaulStovell.TeamBuildMonitorGadget { + /// + /// Interaction logic for MainPage.xaml + /// + public partial class MainPage : System.Windows.Controls.Page { + /// + /// Constructor. + /// + public MainPage() { + InitializeComponent(); + + LoadSettings(); + } + + public static readonly DependencyProperty BuildStoreDriverProperty = DependencyProperty.Register("BuildStoreDriver", typeof(BuildStoreDriver), typeof(MainPage), new UIPropertyMetadata(null)); + public static readonly DependencyProperty FriendlyNameProperty = DependencyProperty.Register("FriendlyName", typeof(string), typeof(MainPage), new UIPropertyMetadata(null)); + + public BuildStoreDriver BuildStoreDriver { + get { return (BuildStoreDriver)GetValue(BuildStoreDriverProperty); } + set { SetValue(BuildStoreDriverProperty, value); } + } + + public string FriendlyName { + get { return (string)GetValue(FriendlyNameProperty); } + set { SetValue(FriendlyNameProperty, value); } + } + + private void BuildItem_Clicked(object sender, RoutedEventArgs e) { + FrameworkElement element = sender as FrameworkElement; + if (element != null) { + BuildSummary summary = element.Tag as BuildSummary; + if (summary != null && summary.DropLocation != null && summary.DropLocation.Length > 0) { + Process.Start(summary.DropLocation); + } + } + } + + private void ExceptionDetailsLink_Clicked(object sender, RoutedEventArgs e) { + if (BuildStoreDriver.LastException != null) { + MessageBox.Show(BuildStoreDriver.LastException.ToString()); + } + } + + private void TryAgainLink_Clicked(object sender, RoutedEventArgs e) { + this.BuildStoreDriver.Monitor(); + } + + private void SettingsLink_Clicked(object sender, RoutedEventArgs e) { + SettingsWindow window = new SettingsWindow(); + window.ShowDialog(); + LoadSettings(); + } + + private void LoadSettings() { + Settings settings = Settings.GetSettings(); + this.FriendlyName = settings.FriendlyName; + + BuildStoreDriver driver = new BuildStoreDriver(); + driver.TeamFoundationServerUri = settings.TeamFoundationServerUri; + driver.TeamProjectName = settings.TeamProjectName; + driver.TeamBuildTypeName = settings.TeamBuildTypeName; + driver.Monitor(); + + this.BuildStoreDriver = driver; + } + } +} \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/Properties/AssemblyInfo.cs b/Source/TeamBuildMonitorGadget/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4e4715c --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/AssemblyInfo.cs @@ -0,0 +1,62 @@ +#region Using directives + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Resources; +using System.Globalization; +using System.Windows; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TeamBuildMonitorGadget")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TeamBuildMonitorGadget")] +[assembly: AssemblyCopyright("Copyright @ 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +// Specifies the location in which theme dictionaries are stored for types in an assembly. +[assembly: ThemeInfo( + // Specifies the location of system theme-specific resource dictionaries for this project. + // The default setting in this project is "None" since this default project does not + // include these user-defined theme files: + // Themes\Aero.NormalColor.xaml + // Themes\Classic.xaml + // Themes\Luna.Homestead.xaml + // Themes\Luna.Metallic.xaml + // Themes\Luna.NormalColor.xaml + // Themes\Royale.NormalColor.xaml + ResourceDictionaryLocation.None, + + // Specifies the location of the system non-theme specific resource dictionary: + // Themes\generic.xaml + ResourceDictionaryLocation.SourceAssembly)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] diff --git a/Source/TeamBuildMonitorGadget/Properties/Resources.Designer.cs b/Source/TeamBuildMonitorGadget/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d1935bf --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PaulStovell.TeamBuildMonitorGadget.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PaulStovell.TeamBuildMonitorGadget.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Source/TeamBuildMonitorGadget/Properties/Resources.resx b/Source/TeamBuildMonitorGadget/Properties/Resources.resx new file mode 100644 index 0000000..e2cc0e0 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/Properties/Settings.Designer.cs b/Source/TeamBuildMonitorGadget/Properties/Settings.Designer.cs new file mode 100644 index 0000000..03fe953 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PaulStovell.TeamBuildMonitorGadget.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Source/TeamBuildMonitorGadget/Properties/Settings.settings b/Source/TeamBuildMonitorGadget/Properties/Settings.settings new file mode 100644 index 0000000..4024694 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/Properties/app.manifest b/Source/TeamBuildMonitorGadget/Properties/app.manifest new file mode 100644 index 0000000..a40d110 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Properties/app.manifest @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/Settings.cs b/Source/TeamBuildMonitorGadget/Settings.cs new file mode 100644 index 0000000..24471cb --- /dev/null +++ b/Source/TeamBuildMonitorGadget/Settings.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Deployment.Application; +using System.Xml.Serialization; +using System.Collections; +using System.Web; +using System.Reflection; + +namespace PaulStovell.TeamBuildMonitorGadget { + public class Settings { + private string _settingsFileName; + private Dictionary _innerSettings; + + private Settings(string fileName) { + _settingsFileName = fileName; + + _innerSettings = new Dictionary(); + if (File.Exists(_settingsFileName)) { + string[] lines = File.ReadAllLines(_settingsFileName); + foreach (string line in lines) { + string[] keyValuePair = line.Split('='); + string key = HttpUtility.UrlDecode(keyValuePair[0]); + string value = HttpUtility.UrlDecode(keyValuePair[1]); + _innerSettings[key] = value; + } + } + } + + public string TeamFoundationServerUri { + get { return GetSetting("TeamFoundationServerUri", "http://myserver:8080"); } + set { SetSetting("TeamFoundationServerUri", value); } + } + + public string TeamProjectName { + get { return GetSetting("TeamProjectName", "MyProjectName"); } + set { SetSetting("TeamProjectName", value); } + } + + public string TeamBuildTypeName { + get { return GetSetting("TeamBuildTypeName", "MyBuildName"); } + set { SetSetting("TeamBuildTypeName", value); } + } + + public string FriendlyName { + get { return GetSetting("FriendlyName", "My project\r\nMy favourite build"); } + set { SetSetting("FriendlyName", value); } + } + + public string SettingsFileName { + get { return _settingsFileName; } + } + + private string GetSetting(string settingName, string defaultValue) { + string result = defaultValue; + if (_innerSettings.ContainsKey(settingName)) { + result = _innerSettings[settingName]; + } + return result; + } + + private void SetSetting(string settingName, string value) { + _innerSettings[settingName] = value; + } + + public void Save() { + List lines = new List(); + foreach (KeyValuePair kvp in _innerSettings) { + lines.Add(HttpUtility.UrlEncode(kvp.Key) + "=" + HttpUtility.UrlEncode(kvp.Value)); + } + File.WriteAllLines(_settingsFileName, lines.ToArray()); + } + + public static Settings GetSettings() { + string startDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location.Replace("file:///", "")); + string filename = Path.Combine(startDirectory, "PaulStovell.NET\\TeamBuildMonitor"); + if (!Directory.Exists(filename)) { + Directory.CreateDirectory(filename); + } + filename = Path.Combine(filename, "Settings.xml"); + return new Settings(filename); + } + } +} diff --git a/Source/TeamBuildMonitorGadget/SettingsWindow.xaml b/Source/TeamBuildMonitorGadget/SettingsWindow.xaml new file mode 100644 index 0000000..fa6247b --- /dev/null +++ b/Source/TeamBuildMonitorGadget/SettingsWindow.xaml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/TeamBuildMonitorGadget/SettingsWindow.xaml.cs b/Source/TeamBuildMonitorGadget/SettingsWindow.xaml.cs new file mode 100644 index 0000000..9e1c3ca --- /dev/null +++ b/Source/TeamBuildMonitorGadget/SettingsWindow.xaml.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace PaulStovell.TeamBuildMonitorGadget { + /// + /// Interaction logic for SettingsWindow.xaml + /// + public partial class SettingsWindow : System.Windows.Window { + public SettingsWindow() { + InitializeComponent(); + + this.Settings = Settings.GetSettings(); + } + + /// + /// DependencyProperty for the Settings property. + /// + public static readonly DependencyProperty SettingsProperty = DependencyProperty.Register("Settings", typeof(Settings), typeof(SettingsWindow), new UIPropertyMetadata(null)); + + /// + /// Gets or sets the settings shown on the dialog. + /// + public Settings Settings { + get { return (Settings)GetValue(SettingsProperty); } + set { SetValue(SettingsProperty, value); } + } + + /// + /// Called when the Save button is clicked. + /// + public void SaveButton_Clicked(object sender, RoutedEventArgs e) { + this.Settings.Save(); + this.Close(); + } + + /// + /// Called when the Cancel button is clicked. + /// + public void CancelButton_Clicked(object sender, RoutedEventArgs e) { + this.Close(); + } + } +} \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget.csproj b/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget.csproj new file mode 100644 index 0000000..6b649e6 --- /dev/null +++ b/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget.csproj @@ -0,0 +1,186 @@ + + + Debug + AnyCPU + {BA7022CF-10AD-4F4A-9C01-86E739B92318} + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + PaulStovell.TeamBuildMonitorGadget + TeamBuildMonitorGadget + 4 + winexe + false + Custom + Program + $(WINDIR)\System32\PresentationHost.exe + -debug "$(MSBuildProjectDirectory)\bin\$(Configuration)\$(AssemblyName)$(ApplicationExtension)" + True + 3.0 + true + false + TeamBuildMonitorGadget_TemporaryKey.pfx + F77084D76CC675AC29126AB31829820F50E2E98C + true + + + Publish\ + false + Disk + false + Foreground + 7 + Days + false + false + false + http://www.paulstovell.net/ + Team Build Monitor Gadget + Paul Stovell + false + true + 1.0.0.%2a + .xbap + true + + + true + full + false + .\bin\Debug\ + DEBUG;TRACE + + + false + true + .\bin\Release\ + TRACE + + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Client.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Common.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Client.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Common.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.VersionControl.Client.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.VersionControl.Common.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.VersionControl.Common.Integration.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.VersionControl.Controls.dll + + + False + C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.TeamFoundation.VersionControl.dll + + + + + + + + + + + + + + + + + + App.xaml + Code + + + + + + Component + + + + + + + MainPage.xaml + + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + Code + SettingsWindow.xaml + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + + False + .NET Framework 2.0 + true + + + + + \ No newline at end of file diff --git a/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget_TemporaryKey.pfx b/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget_TemporaryKey.pfx new file mode 100644 index 0000000..e5ba1a0 Binary files /dev/null and b/Source/TeamBuildMonitorGadget/TeamBuildMonitorGadget_TemporaryKey.pfx differ