From 809e589202d9801f1d3f0a9b89069b829f27e5b6 Mon Sep 17 00:00:00 2001 From: gumme Date: Wed, 30 Apr 2014 10:57:49 +0200 Subject: [PATCH 01/15] Added MarkupExtension tests for testing strings with spaces and commas as parameter (commonly used in file paths), where some tests are currently failing. --- .../Tests/XamlDom/MarkupExtensionTests.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs index 286f94409b..cfe333f062 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/MarkupExtensionTests.cs @@ -27,6 +27,10 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom [TestFixture] public class MarkupExtensionTests : TestHelper { + private const string PathWithSpaces = @"C:\\Folder A\\SubFolder A\\SubFolder B\\file with spaces.txt"; + private const string PathWithoutSpaces = @"C:\\FolderA\\SubFolderA\\SubFolderB\\file.txt"; + private const string PathWithCommasAndSpaces = @"C:\\Folder A\\Sub,Folder,A\\SubFolderB\\file,with,commas and spaces.txt"; + [Test] public void Test1() { @@ -84,6 +88,36 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom { TestMarkupExtension("Content=\"{x:Static t:MyStaticClass.StaticString}\""); } + + [Test] + public void TestPathWithSpaces() + { + TestMarkupExtension("Content=\"{t:String " + PathWithSpaces + "}\""); + } + + [Test] + public void TestQuotedPathWithSpaces() + { + TestMarkupExtension("Content=\"{t:String '" + PathWithSpaces + "'}\""); + } + + [Test] + public void TestPathWithoutSpaces() + { + TestMarkupExtension("Content=\"{t:String " + PathWithoutSpaces + "}\""); + } + + [Test] + public void TestQuotedPathWithoutSpaces() + { + TestMarkupExtension("Content=\"{t:String '" + PathWithoutSpaces + "'}\""); + } + + [Test] + public void TestQuotedPathWithCommasAndSpaces() + { + TestMarkupExtension("Content=\"{t:String '" + PathWithCommasAndSpaces + "'}\""); + } // [Test] // public void Test10() @@ -114,6 +148,23 @@ namespace ICSharpCode.WpfDesign.Tests.XamlDom { public static string StaticString = "a"; } + + public class StringExtension : MarkupExtension + { + readonly string s; + + public StringExtension(string s) + { + TestHelperLog.Log(this.GetType().Name + " " + s); + + this.s = s; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return s; + } + } public class MyExtension : MarkupExtension { From 82099d61faa5106c83dfaa6b85d605adb6407ed8 Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sun, 4 May 2014 20:08:16 +0200 Subject: [PATCH 02/15] Right Click Context Menu for multiple Selected Items to Wrap them in a Container (Grid or Canvas at the Moment!) --- .../RightClickMultipleItemsContextMenu.xaml | 8 + ...RightClickMultipleItemsContextMenu.xaml.cs | 58 ++++++ ...tClickMultipleItemsContextMenuExtension.cs | 54 ++++++ .../WpfDesign.Designer/Project/ModelTools.cs | 172 +++++++++++++++++- .../Project/Translations.cs | 18 ++ .../Project/WpfDesign.Designer.csproj | 5 + .../Extensions/SelectionExtensionServer.cs | 30 ++- 7 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml new file mode 100644 index 0000000000..d6c69df71b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml @@ -0,0 +1,8 @@ + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs new file mode 100644 index 0000000000..e616350d12 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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.Linq; +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 ICSharpCode.WpfDesign.PropertyGrid; +using ICSharpCode.WpfDesign.Designer.Xaml; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + public partial class RightClickMultipleItemsContextMenu + { + private DesignItem designItem; + + public RightClickMultipleItemsContextMenu(DesignItem designItem) + { + this.designItem = designItem; + + InitializeComponent(); + } + + void Click_WrapInCanvas(object sender, System.Windows.RoutedEventArgs e) + { + ModelTools.WrapItemsNewContainer(this.designItem.Services.Selection.SelectedItems, typeof(Canvas)); + } + + void Click_WrapInGrid(object sender, System.Windows.RoutedEventArgs e) + { + ModelTools.WrapItemsNewContainer(this.designItem.Services.Selection.SelectedItems, typeof(Grid)); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs new file mode 100644 index 0000000000..5f24f5caff --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// 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.Windows; +using System.Windows.Media; +using System.Windows.Shapes; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// + /// + [ExtensionServer(typeof(MultipleSelectedExtensionServer))] + [ExtensionFor(typeof(UIElement))] + public class RightClickMultipleItemsContextMenuExtension : SelectionAdornerProvider + { + DesignPanel panel; + + protected override void OnInitialized() + { + base.OnInitialized(); + + panel = ExtendedItem.Context.Services.DesignPanel as DesignPanel; + panel.ContextMenu = new RightClickMultipleItemsContextMenu(ExtendedItem); + } + + protected override void OnRemove() + { + panel.ContextMenu = null; + + base.OnRemove(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs index 73a1510495..f8c8d22406 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs @@ -27,6 +27,7 @@ using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Xps.Serialization; +using ICSharpCode.WpfDesign.Designer.Xaml; namespace ICSharpCode.WpfDesign.Designer { @@ -137,7 +138,7 @@ namespace ICSharpCode.WpfDesign.Designer catch (Exception) { } } - + internal static Size GetDefaultSize(DesignItem createdItem) { CreateVisualTree(createdItem.View); @@ -198,5 +199,174 @@ namespace ICSharpCode.WpfDesign.Designer item.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(newHeight); } } + + + private class ItemPos + { + public HorizontalAlignment HorizontalAlignment{ get; set; } + + public VerticalAlignment VerticalAlignment{ get; set; } + + public double Xmin { get; set; } + + public double Xmax { get; set; } + + public double Ymin { get; set; } + + public double Ymax { get; set; } + + public DesignItem DesignItem { get; set; } + } + + public static void WrapItemsNewContainer(IEnumerable items, Type containerType) + { + var collection = items; + + var _context = collection.First().Context as XamlDesignContext; + + var oldContainer = collection.First().Parent; + + if (collection.Any(x => x.Parent != oldContainer)) + return; + + var newInstance = Activator.CreateInstance(containerType); + DesignItem newPanel = _context.Services.Component.RegisterComponentForDesigner(newInstance); + var changeGroup = newPanel.OpenGroup("Wrap in Container"); + + List itemList = new List(); + + foreach (var item in collection) { + + var itemPos = new ItemPos(){ DesignItem = item }; + itemList.Add(itemPos); + + if (oldContainer.Component is Canvas) { + var canvas = oldContainer.View as Canvas; + + if (item.Properties.GetAttachedProperty(Canvas.RightProperty) != null && item.Properties.GetAttachedProperty(Canvas.RightProperty).IsSet) { + itemPos.HorizontalAlignment = HorizontalAlignment.Right; + itemPos.Xmax = canvas.ActualWidth - (double)item.Properties.GetAttachedProperty(Canvas.RightProperty).ValueOnInstance; + itemPos.Xmin = itemPos.Xmax - ((FrameworkElement)item.View).ActualWidth; + } + else if (item.Properties.GetAttachedProperty(Canvas.LeftProperty) != null && item.Properties.GetAttachedProperty(Canvas.LeftProperty).IsSet) { + itemPos.HorizontalAlignment = HorizontalAlignment.Left; + itemPos.Xmin = (double)item.Properties.GetAttachedProperty(Canvas.LeftProperty).ValueOnInstance; + itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth; + } else { + itemPos.HorizontalAlignment = HorizontalAlignment.Left; + itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth; + } + + if (item.Properties.GetAttachedProperty(Canvas.BottomProperty) != null && item.Properties.GetAttachedProperty(Canvas.BottomProperty).IsSet) { + itemPos.VerticalAlignment = VerticalAlignment.Bottom; + itemPos.Ymax = canvas.ActualHeight - (double)item.Properties.GetAttachedProperty(Canvas.BottomProperty).ValueOnInstance; + itemPos.Ymin = itemPos.Ymax - ((FrameworkElement)item.View).ActualHeight; + } + else if (item.Properties.GetAttachedProperty(Canvas.TopProperty) != null && item.Properties.GetAttachedProperty(Canvas.TopProperty).IsSet) { + itemPos.VerticalAlignment = VerticalAlignment.Top; + itemPos.Ymin = (double)item.Properties.GetAttachedProperty(Canvas.TopProperty).ValueOnInstance; + itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight; + } else { + itemPos.VerticalAlignment = VerticalAlignment.Top; + itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight; + } + + item.Properties.GetAttachedProperty(Canvas.RightProperty).Reset(); + item.Properties.GetAttachedProperty(Canvas.LeftProperty).Reset(); + item.Properties.GetAttachedProperty(Canvas.TopProperty).Reset(); + item.Properties.GetAttachedProperty(Canvas.BottomProperty).Reset(); + } else if (oldContainer.Component is Grid) { + var grid = oldContainer.View as Grid; + + if ((HorizontalAlignment)item.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).ValueOnInstance == HorizontalAlignment.Right) { + itemPos.HorizontalAlignment = HorizontalAlignment.Right; + itemPos.Xmax = grid.ActualWidth - ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Right; + itemPos.Xmin = itemPos.Xmax - ((FrameworkElement)item.View).ActualWidth; + } else { + itemPos.HorizontalAlignment = HorizontalAlignment.Left; + itemPos.Xmin = ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Left; + itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth; + } + + if ((VerticalAlignment)item.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).ValueOnInstance == VerticalAlignment.Bottom) { + itemPos.VerticalAlignment = VerticalAlignment.Bottom; + itemPos.Ymax = grid.ActualHeight - ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Bottom; + itemPos.Ymin = itemPos.Ymax - ((FrameworkElement)item.View).ActualHeight; + } else { + itemPos.VerticalAlignment = VerticalAlignment.Top; + itemPos.Ymin = ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Top; + itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight; + } + + item.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).Reset(); + item.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).Reset(); + item.Properties.GetProperty(FrameworkElement.MarginProperty).Reset(); + } + + var parCol = item.ParentProperty.CollectionElements; + parCol.Remove(item); + } + + var xmin = itemList.Min(x => x.Xmin); + var xmax = itemList.Max(x => x.Xmax); + var ymin = itemList.Min(x => x.Ymin); + var ymax = itemList.Max(x => x.Ymax); + + if (oldContainer.Component is Canvas) { + newPanel.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(xmax - xmin); + newPanel.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(ymax - ymin); + newPanel.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(xmin); + newPanel.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(ymin); + } else if (oldContainer.Component is Grid) { + newPanel.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Left); + newPanel.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Top); + newPanel.Properties.GetProperty(FrameworkElement.MarginProperty).SetValue(new Thickness(xmin, ymin, 0, 0)); + newPanel.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(xmax - xmin); + newPanel.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(ymax - ymin); + } + + foreach (var item in itemList) { + newPanel.ContentProperty.CollectionElements.Add(item.DesignItem); + + if (newPanel.Component is Canvas) { + if (item.HorizontalAlignment == HorizontalAlignment.Right) { + item.DesignItem.Properties.GetAttachedProperty(Canvas.RightProperty).SetValue(xmax - item.Xmax); + } else { + item.DesignItem.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(item.Xmin - xmin); + } + + if (item.VerticalAlignment == VerticalAlignment.Bottom) { + item.DesignItem.Properties.GetAttachedProperty(Canvas.BottomProperty).SetValue(ymax - item.Ymax); + } else { + item.DesignItem.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(item.Ymin - ymin); + } + } else if (newPanel.Component is Grid) { + Thickness thickness = new Thickness(0); + if (item.HorizontalAlignment == HorizontalAlignment.Right) { + item.DesignItem.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Right); + thickness.Right = xmax - item.Xmax; + } else { + item.DesignItem.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Left); + thickness.Left = item.Xmin - xmin; + } + + if (item.VerticalAlignment == VerticalAlignment.Bottom) { + item.DesignItem.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Bottom); + thickness.Bottom = ymax - item.Ymax; + } else { + item.DesignItem.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Top); + thickness.Top = item.Ymin - ymin; + } + + item.DesignItem.Properties.GetProperty(FrameworkElement.MarginProperty).SetValue(thickness); + } + } + + oldContainer.ContentProperty.CollectionElements.Add(newPanel); + + changeGroup.Commit(); + + _context.Services.Selection.SetSelectedComponents(new []{ newPanel }); + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs index 15677480c9..ebb196ca26 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs @@ -65,5 +65,23 @@ namespace ICSharpCode.WpfDesign.Designer return "Press \"Alt\" to Enter Container"; } } + + public virtual string WrapInCanvas { + get { + return "Wrap in Canvas"; + } + } + + public virtual string WrapInGrid { + get { + return "Wrap in Grid"; + } + } + + public virtual string WrapInBorder { + get { + return "Wrap in Border"; + } + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj index 0cb8629e13..ee6c301f7f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj @@ -90,6 +90,10 @@ + + + RightClickMultipleItemsContextMenu.xaml + @@ -263,6 +267,7 @@ + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs index 75db9cd2c4..fc88c441a9 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs @@ -118,7 +118,7 @@ namespace ICSharpCode.WpfDesign.Extensions void OnSelectionChanged(object sender, EventArgs e) { - ReapplyExtensions(this.Services.Selection.SelectedItems); + ReapplyExtensions(this.Services.Selection.SelectedItems); } /// @@ -130,6 +130,34 @@ namespace ICSharpCode.WpfDesign.Extensions } } + /// + /// Applies an extension only when multiple Items are selected! + /// + public class MultipleSelectedExtensionServer : DefaultExtensionServer + { + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + this.Services.Selection.SelectionChanged += OnSelectionChanged; + } + + void OnSelectionChanged(object sender, EventArgs e) + { + ReapplyExtensions(this.Services.Selection.SelectedItems); + } + + /// + /// Gets if the item is in the secondary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return Services.Selection.SelectionCount > 1; + } + } + /// /// Applies an extension to the primary selection if Only One Item is Selected. /// From df4cd4b1c6e42d7ddaa609ef559ab9565e486fc7 Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sun, 4 May 2014 20:43:00 +0200 Subject: [PATCH 03/15] A few WhiteSpace fixes and Comments removed. --- .../Project/Controls/RotateThumb.cs | 8 -- .../Project/Controls/SizeDisplay.cs | 40 +++++----- .../Project/Extensions/Initializers.cs | 74 +++++++++---------- .../WpfDesign/WpfDesign/Project/Services.cs | 50 ++++++------- 4 files changed, 82 insertions(+), 90 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs index f09d24855f..61a9257ee2 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs @@ -32,14 +32,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls { public class RotateThumb : ResizeThumb { -// private double initialAngle; -// private RotateTransform rotateTransform; -// private Vector startVector; -// private Point centerPoint; -// private Control designerItem; -// private Panel canvas; -// private AdornerPanel parent; - static RotateThumb() { DefaultStyleKeyProperty.OverrideMetadata(typeof(RotateThumb), new FrameworkPropertyMetadata(typeof(RotateThumb))); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/SizeDisplay.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/SizeDisplay.cs index 9f75cdb161..8f660b84db 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/SizeDisplay.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/SizeDisplay.cs @@ -26,25 +26,25 @@ using System.Windows.Controls; namespace ICSharpCode.WpfDesign.Designer.Controls { - /// - /// Display height of the element. - /// - class HeightDisplay : Control - { - static HeightDisplay() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(HeightDisplay), new FrameworkPropertyMetadata(typeof(HeightDisplay))); - } - } + /// + /// Display height of the element. + /// + class HeightDisplay : Control + { + static HeightDisplay() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(HeightDisplay), new FrameworkPropertyMetadata(typeof(HeightDisplay))); + } + } - /// - /// Display width of the element. - /// - class WidthDisplay : Control - { - static WidthDisplay() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(WidthDisplay), new FrameworkPropertyMetadata(typeof(WidthDisplay))); - } - } + /// + /// Display width of the element. + /// + class WidthDisplay : Control + { + static WidthDisplay() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(WidthDisplay), new FrameworkPropertyMetadata(typeof(WidthDisplay))); + } + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs index 4486c4730e..433d48f307 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs @@ -30,55 +30,55 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions.Initializers { public override void InitializeDefaults(DesignItem item) { - //Not every Content Control can have a text as Content (e.g. ZoomBox of WPF Toolkit) - if (item.Component is Button) - { + //Not every Content Control can have a text as Content (e.g. ZoomBox of WPF Toolkit) + if (item.Component is Button) + { DesignItemProperty contentProperty = item.Properties["Content"]; - if (contentProperty.ValueOnInstance == null) - { + if (contentProperty.ValueOnInstance == null) + { contentProperty.SetValue(item.ComponentType.Name); } } - DesignItemProperty verticalAlignmentProperty = item.Properties["VerticalAlignment"]; - if (verticalAlignmentProperty.ValueOnInstance == null) - { - verticalAlignmentProperty.SetValue(VerticalAlignment.Center); - } + DesignItemProperty verticalAlignmentProperty = item.Properties["VerticalAlignment"]; + if (verticalAlignmentProperty.ValueOnInstance == null) + { + verticalAlignmentProperty.SetValue(VerticalAlignment.Center); + } - DesignItemProperty horizontalAlignmentProperty = item.Properties["HorizontalAlignment"]; - if (horizontalAlignmentProperty.ValueOnInstance == null) - { - horizontalAlignmentProperty.SetValue(HorizontalAlignment.Center); - } + DesignItemProperty horizontalAlignmentProperty = item.Properties["HorizontalAlignment"]; + if (horizontalAlignmentProperty.ValueOnInstance == null) + { + horizontalAlignmentProperty.SetValue(HorizontalAlignment.Center); + } } } [ExtensionFor(typeof(TextBlock))] - public class TextBlockInitializer : DefaultInitializer - { - public override void InitializeDefaults(DesignItem item) - { - DesignItemProperty textProperty = item.Properties["Text"]; - if (textProperty.ValueOnInstance == null || textProperty.ValueOnInstance.ToString() == "") - { - textProperty.SetValue(item.ComponentType.Name); - } + public class TextBlockInitializer : DefaultInitializer + { + public override void InitializeDefaults(DesignItem item) + { + DesignItemProperty textProperty = item.Properties["Text"]; + if (textProperty.ValueOnInstance == null || textProperty.ValueOnInstance.ToString() == "") + { + textProperty.SetValue(item.ComponentType.Name); + } - DesignItemProperty verticalAlignmentProperty = item.Properties["VerticalAlignment"]; - if (verticalAlignmentProperty.ValueOnInstance == null) - { - verticalAlignmentProperty.SetValue(VerticalAlignment.Center); - } + DesignItemProperty verticalAlignmentProperty = item.Properties["VerticalAlignment"]; + if (verticalAlignmentProperty.ValueOnInstance == null) + { + verticalAlignmentProperty.SetValue(VerticalAlignment.Center); + } - DesignItemProperty horizontalAlignmentProperty = item.Properties["HorizontalAlignment"]; - if (horizontalAlignmentProperty.ValueOnInstance == null) - { - horizontalAlignmentProperty.SetValue(HorizontalAlignment.Center); - } - } + DesignItemProperty horizontalAlignmentProperty = item.Properties["HorizontalAlignment"]; + if (horizontalAlignmentProperty.ValueOnInstance == null) + { + horizontalAlignmentProperty.SetValue(HorizontalAlignment.Center); + } + } } - + [ExtensionFor(typeof(HeaderedContentControl), OverrideExtension = typeof(ContentControlInitializer))] public class HeaderedContentControlInitializer : DefaultInitializer { @@ -96,7 +96,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions.Initializers } } - [ExtensionFor(typeof(Shape))] + [ExtensionFor(typeof(Shape))] public class ShapeInitializer : DefaultInitializer { public override void InitializeDefaults(DesignItem item) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs index 45940506e6..2f95f1b266 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs @@ -233,33 +233,33 @@ namespace ICSharpCode.WpfDesign #region IKeyBindingService /// - /// Service that handles all the key bindings in the designer. - /// - public interface IKeyBindingService - { - /// - /// Gets the object to which the bindings are being applied - /// - object Owner { get; } + /// Service that handles all the key bindings in the designer. + /// + public interface IKeyBindingService + { + /// + /// Gets the object to which the bindings are being applied + /// + object Owner { get; } - /// - /// Register with . - /// - /// The binding to be applied. - void RegisterBinding(KeyBinding binding); + /// + /// Register with . + /// + /// The binding to be applied. + void RegisterBinding(KeyBinding binding); - /// - /// De-register with . - /// - /// The binding to be applied. - void DeregisterBinding(KeyBinding binding); + /// + /// De-register with . + /// + /// The binding to be applied. + void DeregisterBinding(KeyBinding binding); - /// - /// Gets binding for the corresponding gesture otherwise returns null. - /// - /// The keyboard gesture requested. - KeyBinding GetBinding(KeyGesture gesture); - } - + /// + /// Gets binding for the corresponding gesture otherwise returns null. + /// + /// The keyboard gesture requested. + KeyBinding GetBinding(KeyGesture gesture); + } + #endregion } From 300417bb5f68582f2b628df7e93f14c4bd820c22 Mon Sep 17 00:00:00 2001 From: gumme Date: Wed, 7 May 2014 14:34:01 +0200 Subject: [PATCH 04/15] Added tests for undo/redo operations on implicit and explicit lists. Fixed bug where explicit collection was not handled correctly when resetting a XamlProperty. --- .../Tests/Designer/ModelTests.cs | 78 +++++++++++++++++++ .../WpfDesign.XamlDom/Project/XamlProperty.cs | 10 ++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index dc675552f7..bc0d55de97 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -149,6 +149,84 @@ namespace ICSharpCode.WpfDesign.Tests.Designer AssertLog(""); } + [Test] + public void UndoRedoImplicitList() + { + UndoRedoListInternal(false); + } + + [Test] + public void UndoRedoExplicitList() + { + UndoRedoListInternal(true); + } + + void UndoRedoListInternal(bool useExplicitList) + { + DesignItem button = CreateCanvasContext(""; + } + else { + expectedXamlWithList = @""; + } + + DesignItem exampleClassItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass()); + exampleClassItem.Properties["StringProp"].SetValue("String value"); + otherListProp.CollectionElements.Add(exampleClassItem); + + button.Properties["Tag"].SetValue(containerItem); + g.Commit(); + } + + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithList, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Undo(); + Assert.IsFalse(s.CanUndo); + Assert.IsTrue(s.CanRedo); + AssertCanvasDesignerOutput("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Redo(); + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithList, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + AssertLog(""); + } [Test] public void AddTextBoxToCanvas() diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index 9fbeab0717..eee4a6848e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -254,13 +254,21 @@ namespace ICSharpCode.WpfDesign.XamlDom void ResetInternal() { + bool isExplicitCollection = false; + if (propertyValue != null) { + isExplicitCollection = IsCollection; + propertyValue.RemoveNodeFromParent(); propertyValue.ParentProperty = null; propertyValue = null; } if (_propertyElement != null) { - _propertyElement.ParentNode.RemoveChild(_propertyElement); + Debug.Assert(!isExplicitCollection || _propertyElement.ParentNode == null); + + if (!isExplicitCollection) { + _propertyElement.ParentNode.RemoveChild(_propertyElement); + } _propertyElement = null; } } From c410a20a75f39d1e9ab07385641db18d2655cba8 Mon Sep 17 00:00:00 2001 From: tbulle Date: Thu, 8 May 2014 14:52:30 +0200 Subject: [PATCH 05/15] Nullable ResizeThumbAlignment to enable both top and bottom snap on resize simultaneously --- .../Project/Extensions/SnaplinePlacementBehavior.cs | 4 ++-- .../WpfDesign/WpfDesign/Project/PlacementInformation.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs index 67868fbfb7..8242243e39 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -115,7 +115,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) { if (operation.Type == PlacementType.Resize) { - if (info.ResizeThumbAlignment.Vertical == VerticalAlignment.Top) { + if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Vertical == VerticalAlignment.Top) { bounds.Y += delta; bounds.Height = Math.Max(0, bounds.Height - delta); } else { @@ -138,7 +138,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) { if (operation.Type == PlacementType.Resize) { - if (info.ResizeThumbAlignment.Horizontal == HorizontalAlignment.Left) { + if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Horizontal == HorizontalAlignment.Left) { bounds.X += delta; bounds.Width = Math.Max(0, bounds.Width - delta); } else { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementInformation.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementInformation.cs index fa880e42ed..34832763b3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementInformation.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementInformation.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.WpfDesign /// /// Gets/sets the alignment of the resize thumb used to start the operation. /// - public PlacementAlignment ResizeThumbAlignment { get; set; } + public PlacementAlignment? ResizeThumbAlignment { get; set; } /// public override string ToString() From 5ccc93f254dfe3ddc120beaca105c0fca50742f1 Mon Sep 17 00:00:00 2001 From: gumme Date: Fri, 9 May 2014 07:34:14 +0200 Subject: [PATCH 06/15] Added tests for undo/redo operations on implicit and explicit dictionaries. Added tests for clearing explicit lists and dictionaries. Fixed so an IDictionary item is removed using the item key. --- .../Tests/Designer/ModelTests.cs | 183 +++++++++++++++++- .../Project/CollectionElementsCollection.cs | 3 +- .../Project/CollectionSupport.cs | 15 ++ 3 files changed, 196 insertions(+), 5 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs index bc0d55de97..44d4611df9 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTests.cs @@ -167,6 +167,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer UndoService s = button.Context.Services.GetService(); IComponentService component = button.Context.Services.Component; string expectedXamlWithList; + DesignItemProperty otherListProp; Assert.IsFalse(s.CanUndo); Assert.IsFalse(s.CanRedo); @@ -174,7 +175,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer using (ChangeGroup g = button.OpenGroup("UndoRedoListInternal test")) { DesignItem containerItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassContainer()); - var otherListProp = containerItem.Properties["OtherList"]; + otherListProp = containerItem.Properties["OtherList"]; if(useExplicitList) { otherListProp.SetValue(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassList()); @@ -190,8 +191,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer "; - } - else { + } else { expectedXamlWithList = @""; + } else { + expectedXamlWithDictionary = @""; + } + + DesignItem exampleClassItem = component.RegisterComponentForDesigner(new ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClass()); + exampleClassItem.Key = "testKey"; + exampleClassItem.Properties["StringProp"].SetValue("String value"); + dictionaryProp.CollectionElements.Add(exampleClassItem); + + button.Properties["Tag"].SetValue(containerItem); + g.Commit(); + } + + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithDictionary, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + dictionaryProp = button.Properties["Tag"].Value.Properties["Dictionary"]; + Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary)dictionaryProp.ValueOnInstance).Count == dictionaryProp.CollectionElements.Count); + + s.Undo(); + Assert.IsFalse(s.CanUndo); + Assert.IsTrue(s.CanRedo); + AssertCanvasDesignerOutput("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + s.Redo(); + Assert.IsTrue(s.CanUndo); + Assert.IsFalse(s.CanRedo); + AssertCanvasDesignerOutput(expectedXamlWithDictionary, button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + + dictionaryProp = button.Properties["Tag"].Value.Properties["Dictionary"]; + Assert.IsTrue(((ICSharpCode.WpfDesign.Tests.XamlDom.ExampleClassDictionary)dictionaryProp.ValueOnInstance).Count == dictionaryProp.CollectionElements.Count); + AssertLog(""); - } + } [Test] public void AddTextBoxToCanvas() @@ -332,6 +424,89 @@ namespace ICSharpCode.WpfDesign.Tests.Designer AssertLog(""); } + [Test] + public void ClearExplicitList() + { + DesignItem button = CreateCanvasContext("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + AssertLog(""); + } + + [Test] + public void ClearExplicitDictionary() + { + DesignItem button = CreateCanvasContext("", button.Context, "xmlns:Controls0=\"" + ICSharpCode.WpfDesign.Tests.XamlDom.XamlTypeFinderTests.XamlDomTestsNamespace + "\""); + AssertLog(""); + } + [Test] public void AddMultiBindingToTextBox() { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs index 86bc31adef..6566897e28 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs @@ -54,7 +54,8 @@ namespace ICSharpCode.WpfDesign.XamlDom XamlPropertyInfo info = property.propertyInfo; object collection = info.GetValue(property.ParentObject.Instance); if (!CollectionSupport.RemoveItemAt(info.ReturnType, collection, index)) { - CollectionSupport.RemoveItem(info.ReturnType, collection, this[index].GetValueFor(info)); + var propertyValue = this[index]; + CollectionSupport.RemoveItem(info.ReturnType, collection, propertyValue.GetValueFor(info), propertyValue); } this[index].RemoveNodeFromParent(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs index cf36fed5a4..09a3b28beb 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs @@ -154,5 +154,20 @@ namespace ICSharpCode.WpfDesign.XamlDom new object[] { item }, CultureInfo.InvariantCulture); } + + /// + /// Removes an item instance from the specified collection. + /// + internal static void RemoveItem(Type collectionType, object collectionInstance, object item, XamlPropertyValue element) + { + var dictionary = collectionInstance as IDictionary; + var xamlObject = element as XamlObject; + + if (dictionary != null && xamlObject != null) { + dictionary.Remove(xamlObject.GetXamlAttribute("Key")); + } else { + RemoveItem(collectionType, collectionInstance, item); + } + } } } From 428558da6b57fc5bc782f5f8bfddda908983c891 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 12 May 2014 07:42:47 +0200 Subject: [PATCH 07/15] Beta 4 designation --- src/Main/GlobalAssemblyInfo.cs.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main/GlobalAssemblyInfo.cs.template b/src/Main/GlobalAssemblyInfo.cs.template index 796f82f16a..24cb65ee69 100644 --- a/src/Main/GlobalAssemblyInfo.cs.template +++ b/src/Main/GlobalAssemblyInfo.cs.template @@ -46,7 +46,7 @@ internal static class RevisionClass public const string Minor = "0"; public const string Build = "0"; public const string Revision = "$INSERTREVISION$"; - public const string VersionName = "Beta 3"; // "" is not valid for no version name, you have to use null if you don't want a version name (eg "Beta 1") + public const string VersionName = "Beta 4"; // "" is not valid for no version name, you have to use null if you don't want a version name (eg "Beta 1") public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$"; } From 015392744710534a73079377f8acf052544d9f9a Mon Sep 17 00:00:00 2001 From: Linquize Date: Wed, 14 May 2014 18:15:40 +0800 Subject: [PATCH 08/15] Add trailing newline when generating InitializeComponents() This matches VS behavior --- .../Project/Src/FormsDesigner/CSharpDesignerGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs index ef39be8a3d..2fd3560e6f 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs @@ -182,7 +182,7 @@ namespace CSharpBinding.FormsDesigner string newline = DocumentUtilities.GetLineTerminator(script.OriginalDocument, bodyRegion.BeginLine); string indentation = DocumentUtilities.GetIndentation(script.OriginalDocument, bodyRegion.BeginLine); - string code = "{" + newline + GenerateInitializeComponents(codeMethod, indentation, newline) + indentation + "}"; + string code = "{" + newline + GenerateInitializeComponents(codeMethod, indentation, newline) + newline + indentation + "}"; int startOffset = script.GetCurrentOffset(bodyRegion.Begin); int endOffset = script.GetCurrentOffset(bodyRegion.End); From c825585043caa94fe741a7970728c160fa48fed1 Mon Sep 17 00:00:00 2001 From: tbulle Date: Wed, 14 May 2014 14:56:47 +0200 Subject: [PATCH 09/15] Simplification of code --- .../Project/Extensions/SnaplinePlacementBehavior.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs index 8242243e39..b145816386 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -116,11 +116,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (operation.Type == PlacementType.Resize) { if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Vertical == VerticalAlignment.Top) { - bounds.Y += delta; - bounds.Height = Math.Max(0, bounds.Height - delta); - } else { - bounds.Height = Math.Max(0, bounds.Height + delta); + bounds.Y += delta; } + bounds.Height = Math.Max(0, bounds.Height - delta); info.Bounds = bounds; } else { foreach (var item in operation.PlacedItems) { @@ -139,11 +137,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (operation.Type == PlacementType.Resize) { if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Horizontal == HorizontalAlignment.Left) { - bounds.X += delta; - bounds.Width = Math.Max(0, bounds.Width - delta); - } else { - bounds.Width = Math.Max(0, bounds.Width + delta); + bounds.X += delta; } + bounds.Width = Math.Max(0, bounds.Width - delta); info.Bounds = bounds; } else { foreach (var item in operation.PlacedItems) { From a6a9bfe7c2b4eba2b602578b913576f143355717 Mon Sep 17 00:00:00 2001 From: tbulle Date: Wed, 14 May 2014 16:05:15 +0200 Subject: [PATCH 10/15] Fixed so that MarkupExtensionParser doesent ignore escaped backslash --- .../WpfDesign.XamlDom/Project/MarkupExtensionParser.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs index 30791350c1..6fcfa1fe59 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs @@ -97,8 +97,10 @@ namespace ICSharpCode.WpfDesign.XamlDom char quote = text[pos++]; CheckNotEOF(); while (!(text[pos] == quote && text[pos-1] != '\\')) { + char prev = text[pos-1]; char c = text[pos++]; - if (c != '\\') + bool isEscapedBackslash = string.Concat(prev,c)=="\\\\"; + if (c != '\\' || isEscapedBackslash) b.Append(c); CheckNotEOF(); } From 66972166231fd4ea0145ff15f3d02b7024468510 Mon Sep 17 00:00:00 2001 From: tbulle Date: Thu, 15 May 2014 00:15:45 +0200 Subject: [PATCH 11/15] Fixed bug that double escaped backslashes became three backslashes after parsing --- .../Project/MarkupExtensionParser.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs index 6fcfa1fe59..713701b963 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/MarkupExtensionParser.cs @@ -96,12 +96,17 @@ namespace ICSharpCode.WpfDesign.XamlDom if (text[pos] == '"' || text[pos] == '\'') { char quote = text[pos++]; CheckNotEOF(); + int lastBackslashPos = -1; while (!(text[pos] == quote && text[pos-1] != '\\')) { - char prev = text[pos-1]; + int current = pos; char c = text[pos++]; - bool isEscapedBackslash = string.Concat(prev,c)=="\\\\"; - if (c != '\\' || isEscapedBackslash) + //check if string is \\ and that the last backslash is not the previously saved char, ie that \\\\ does not become \\\ but just \\ + bool isEscapedBackslash = string.Concat(text[current-1],c)=="\\\\" && current-1 != lastBackslashPos; + if (c != '\\' || isEscapedBackslash){ b.Append(c); + if(isEscapedBackslash) + lastBackslashPos = current; + } CheckNotEOF(); } pos++; // consume closing quote From 7c5b1f93f0572562df7d4b9508ea9fafe7ee7f88 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 16 May 2014 23:14:08 +0200 Subject: [PATCH 12/15] XAML CC: do not insert equals sign and quotation marks while trying to type the name of an attached property/event --- .../XamlBinding/XamlBinding/XamlCompletionItemList.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs index 1138d7fe84..054ae638f6 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs @@ -83,10 +83,12 @@ namespace ICSharpCode.XamlBinding XamlCompletionItem cItem = item as XamlCompletionItem; if (xamlContext.Description == XamlContextDescription.InTag) { - context.Editor.Document.Insert(context.EndOffset, "=\"\""); - context.CompletionCharHandled = context.CompletionChar == '='; - context.Editor.Caret.Offset--; - new XamlCodeCompletionBinding().CtrlSpace(context.Editor); + if (cItem.Entity.SymbolKind == SymbolKind.Property || cItem.Entity.SymbolKind == SymbolKind.Event) { + context.Editor.Document.Insert(context.EndOffset, "=\"\""); + context.CompletionCharHandled = context.CompletionChar == '='; + context.Editor.Caret.Offset--; + new XamlCodeCompletionBinding().CtrlSpace(context.Editor); + } } else if (xamlContext.Description == XamlContextDescription.InMarkupExtension && !string.IsNullOrEmpty(xamlContext.RawAttributeValue)) { string valuePart = xamlContext.RawAttributeValue.Substring(0, xamlContext.ValueStartOffset); AttributeValue value = MarkupExtensionParser.ParseValue(valuePart); From 70fd9337bdd3696025305fb594cce3b450b4fd36 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 18 May 2014 18:55:51 +0100 Subject: [PATCH 13/15] Support solution specific NuGet.Config files. If a solution has its own NuGet.Config file this will be read and any package sources defined in this file will be available in the list of package sources in the Manage Packages dialog. --- .../Project/PackageManagement.csproj | 4 +- .../FakePackageManagementProjectService.cs | 1 + .../Project/Src/ISettingsFactory.cs | 28 ----- .../Project/Src/ISettingsProvider.cs | 14 +++ .../Project/Src/PackageManagementOptions.cs | 10 +- .../Src/RegisteredPackageSourceSettings.cs | 36 +++++- .../Project/Src/SettingsFactory.cs | 32 ----- .../Project/Src/SettingsProvider.cs | 62 ++++++++++ .../Test/PackageManagement.Tests.csproj | 2 +- .../Test/Src/Helpers/FakeSettingsFactory.cs | 37 ------ .../TestablePackageManagementOptions.cs | 22 +++- .../Test/Src/PackageManagementOptionsTests.cs | 115 +++++++++++++++++- .../PackageManagementOptionsViewModelTests.cs | 4 +- .../Test/Src/SettingsProviderTests.cs | 80 ++++++++++++ 14 files changed, 333 insertions(+), 114 deletions(-) delete mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/ISettingsFactory.cs create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/ISettingsProvider.cs delete mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/SettingsFactory.cs create mode 100644 src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs delete mode 100644 src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeSettingsFactory.cs create mode 100644 src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index d1e99f1ec2..cdb4f112ec 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -154,6 +154,7 @@ + @@ -219,7 +220,6 @@ - @@ -252,6 +252,7 @@ + @@ -400,7 +401,6 @@ Code - diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs index cba1708045..8692456254 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs @@ -43,6 +43,7 @@ namespace ICSharpCode.PackageManagement.Design public void FireSolutionClosedEvent(ISolution solution) { + OpenSolution = null; if (SolutionClosed != null) { SolutionClosed(this, new SolutionEventArgs(solution)); } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsFactory.cs b/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsFactory.cs deleted file mode 100644 index 9167745e5c..0000000000 --- a/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// 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 NuGet; - -namespace ICSharpCode.PackageManagement -{ - public interface ISettingsFactory - { - ISettings CreateSettings(string directory); - } -} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsProvider.cs b/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsProvider.cs new file mode 100644 index 0000000000..8a0a210b61 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/ISettingsProvider.cs @@ -0,0 +1,14 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public interface ISettingsProvider + { + event EventHandler SettingsChanged; + ISettings LoadSettings(); + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptions.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptions.cs index 6200ce200b..655d9be0d1 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptions.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementOptions.cs @@ -35,15 +35,17 @@ namespace ICSharpCode.PackageManagement ObservableCollection recentPackages; PackageRestoreConsent packageRestoreConsent; - public PackageManagementOptions(Properties properties, ISettings settings) + public PackageManagementOptions( + Properties properties, + ISettingsProvider settingsProvider) { this.properties = properties; - registeredPackageSourceSettings = new RegisteredPackageSourceSettings(settings); - packageRestoreConsent = new PackageRestoreConsent(settings); + registeredPackageSourceSettings = new RegisteredPackageSourceSettings(settingsProvider); + packageRestoreConsent = new PackageRestoreConsent(settingsProvider.LoadSettings()); } public PackageManagementOptions(Properties properties) - : this(properties, Settings.LoadDefaultSettings(null, null, null)) + : this(properties, new SettingsProvider()) { } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs b/src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs index ba79003f2a..2a6aae2c30 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/RegisteredPackageSourceSettings.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; +using ICSharpCode.SharpDevelop.Project; using NuGet; namespace ICSharpCode.PackageManagement @@ -35,20 +36,32 @@ namespace ICSharpCode.PackageManagement new PackageSource("(Aggregate source)", "All"); ISettings settings; + ISettingsProvider settingsProvider; PackageSource defaultPackageSource; RegisteredPackageSources packageSources; PackageSource activePackageSource; - public RegisteredPackageSourceSettings(ISettings settings) - : this(settings, RegisteredPackageSources.DefaultPackageSource) + public RegisteredPackageSourceSettings(ISettingsProvider settingsProvider) + : this(settingsProvider, RegisteredPackageSources.DefaultPackageSource) { } - public RegisteredPackageSourceSettings(ISettings settings, PackageSource defaultPackageSource) + public RegisteredPackageSourceSettings( + ISettingsProvider settingsProvider, + PackageSource defaultPackageSource) { - this.settings = settings; + this.settingsProvider = settingsProvider; this.defaultPackageSource = defaultPackageSource; + + settings = settingsProvider.LoadSettings(); + ReadActivePackageSource(); + RegisterSolutionEvents(); + } + + void RegisterSolutionEvents() + { + settingsProvider.SettingsChanged += SettingsChanged; } void ReadActivePackageSource() @@ -176,5 +189,20 @@ namespace ICSharpCode.PackageManagement { settings.SetValue(ActivePackageSourceSectionName, activePackageSource.Key, activePackageSource.Value); } + + void SettingsChanged(object sender, EventArgs e) + { + settings = settingsProvider.LoadSettings(); + ReadActivePackageSource(); + ResetPackageSources(); + } + + void ResetPackageSources() + { + if (packageSources != null) { + packageSources.CollectionChanged -= PackageSourcesChanged; + packageSources = null; + } + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/SettingsFactory.cs b/src/AddIns/Misc/PackageManagement/Project/Src/SettingsFactory.cs deleted file mode 100644 index 807072f3e5..0000000000 --- a/src/AddIns/Misc/PackageManagement/Project/Src/SettingsFactory.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// 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 NuGet; - -namespace ICSharpCode.PackageManagement -{ - public class SettingsFactory : ISettingsFactory - { - public ISettings CreateSettings(string directory) - { - var fileSystem = new PhysicalFileSystem(directory); - return new Settings(fileSystem); - } - } -} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs b/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs new file mode 100644 index 0000000000..016c27749e --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs @@ -0,0 +1,62 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.SharpDevelop.Project; +using NuGet; + +namespace ICSharpCode.PackageManagement +{ + public class SettingsProvider : ISettingsProvider + { + public static Func LoadDefaultSettings + = Settings.LoadDefaultSettings; + + IPackageManagementProjectService projectService; + + public SettingsProvider() + : this(PackageManagementServices.ProjectService) + { + } + + public SettingsProvider(IPackageManagementProjectService projectService) + { + this.projectService = projectService; + projectService.SolutionOpened += OnSettingsChanged; + projectService.SolutionClosed += OnSettingsChanged; + } + + public event EventHandler SettingsChanged; + + void OnSettingsChanged(object sender, SolutionEventArgs e) + { + if (SettingsChanged != null) { + SettingsChanged(this, new EventArgs()); + } + } + + public ISettings LoadSettings() + { + return LoadSettings(GetSolutionDirectory()); + } + + string GetSolutionDirectory() + { + ISolution solution = projectService.OpenSolution; + if (solution != null) { + return solution.Directory; + } + return null; + } + + ISettings LoadSettings(string directory) + { + if (directory == null) { + return LoadDefaultSettings(null, null, null); + } + + return LoadDefaultSettings(new PhysicalFileSystem(directory), null, null); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj index 6dab719b65..fb3cc11e72 100644 --- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj +++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj @@ -176,7 +176,6 @@ - @@ -195,6 +194,7 @@ + diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeSettingsFactory.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeSettingsFactory.cs deleted file mode 100644 index c6ad46bacc..0000000000 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakeSettingsFactory.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team -// -// 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 ICSharpCode.PackageManagement; -using ICSharpCode.PackageManagement.Design; -using NuGet; - -namespace PackageManagement.Tests.Helpers -{ - public class FakeSettingsFactory : ISettingsFactory - { - public FakeSettings FakeSettings = new FakeSettings(); - public string DirectoryPassedToCreateSettings; - - public ISettings CreateSettings(string directory) - { - DirectoryPassedToCreateSettings = directory; - return FakeSettings; - } - } -} diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs index f454689290..2f415b5ad8 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs @@ -29,15 +29,31 @@ namespace PackageManagement.Tests.Helpers public FakeSettings FakeSettings; public TestablePackageManagementOptions() - : this(new Properties(), new FakeSettings()) + : this(new Properties(), new FakeSettings(), new FakePackageManagementProjectService()) { } - public TestablePackageManagementOptions(Properties properties, FakeSettings fakeSettings) - : base(properties, fakeSettings) + public TestablePackageManagementOptions( + Properties properties, + FakeSettings fakeSettings, + FakePackageManagementProjectService projectService) + : base(properties, CreateSettingsProvider(fakeSettings, projectService)) { this.Properties = properties; this.FakeSettings = fakeSettings; } + + public static void ChangeSettingsReturnedBySettingsProvider(FakeSettings settings) + { + SettingsProvider.LoadDefaultSettings = (fileSystem, configFile, machineSettings) => { + return settings; + }; + } + + public static SettingsProvider CreateSettingsProvider(FakeSettings fakeSettings, FakePackageManagementProjectService projectService) + { + ChangeSettingsReturnedBySettingsProvider(fakeSettings); + return new SettingsProvider(projectService); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs index b5673a5a41..29a111a445 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsTests.cs @@ -36,6 +36,8 @@ namespace PackageManagement.Tests Properties properties; PackageManagementOptions options; FakeSettings fakeSettings; + SettingsProvider settingsProvider; + FakePackageManagementProjectService projectService; void CreateOptions() { @@ -63,12 +65,26 @@ namespace PackageManagement.Tests void CreateOptions(FakeSettings fakeSettings) { CreateProperties(); - options = new PackageManagementOptions(properties, fakeSettings); + CreateSettingsProvider(fakeSettings); + options = new PackageManagementOptions(properties, settingsProvider); + } + + void CreateSettingsProvider(FakeSettings fakeSettings) + { + projectService = new FakePackageManagementProjectService(); + settingsProvider = TestablePackageManagementOptions.CreateSettingsProvider(fakeSettings, projectService); + } + + void ChangeSettingsReturnedBySettingsProvider() + { + fakeSettings = new FakeSettings(); + TestablePackageManagementOptions.ChangeSettingsReturnedBySettingsProvider(fakeSettings); } void CreateOptions(Properties properties, FakeSettings fakeSettings) { - options = new PackageManagementOptions(properties, fakeSettings); + CreateSettingsProvider(fakeSettings); + options = new PackageManagementOptions(properties, settingsProvider); } void SaveOptions() @@ -88,6 +104,18 @@ namespace PackageManagement.Tests fakeSettings.SetPackageRestoreSetting(true); } + void OpenSolution() + { + var helper = new SolutionHelper(@"d:\projects\MyProject\MySolution.sln"); + projectService.FireSolutionOpenedEvent(helper.MSBuildSolution); + } + + void CloseSolution() + { + var helper = new SolutionHelper(@"d:\projects\MyProject\MySolution.sln"); + projectService.FireSolutionClosedEvent(helper.MSBuildSolution); + } + [Test] public void PackageSources_OnePackageSourceInSettings_ContainsSinglePackageSourceFromSettings() { @@ -465,5 +493,88 @@ namespace PackageManagement.Tests KeyValuePair keyValuePair = fakeSettings.GetValuePassedToSetValueForPackageRestoreSection(); Assert.AreEqual("False", keyValuePair.Value); } + + [Test] + public void PackageSources_SolutionOpenedAfterInitialPackageSourcesLoaded_ContainsPackageSourceFromSolutionSpecificSettings() + { + CreateSettings(); + var packageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.AddFakePackageSource(packageSource); + CreateOptions(fakeSettings); + RegisteredPackageSources initialSources = options.PackageSources; + var expectedInitialSources = new List(); + expectedInitialSources.Add(packageSource); + ChangeSettingsReturnedBySettingsProvider(); + packageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.AddFakePackageSource(packageSource); + var expectedSources = new List(); + expectedSources.Add(packageSource); + packageSource = new PackageSource("http://nuget.org", "ProjectSource"); + fakeSettings.AddFakePackageSource(packageSource); + expectedSources.Add(packageSource); + OpenSolution(); + + RegisteredPackageSources actualSources = options.PackageSources; + + Assert.AreEqual(expectedInitialSources, initialSources); + Assert.AreEqual(expectedSources, actualSources); + } + + [Test] + public void PackageSources_SolutionClosedAfterInitialPackageSourcesLoaded_PackageSourcesReloaded() + { + CreateSettings(); + var packageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.AddFakePackageSource(packageSource); + var expectedInitialSources = new List(); + expectedInitialSources.Add(packageSource); + packageSource = new PackageSource("http://nuget.org", "ProjectSource"); + fakeSettings.AddFakePackageSource(packageSource); + expectedInitialSources.Add(packageSource); + OpenSolution(); + CreateOptions(fakeSettings); + RegisteredPackageSources initialSources = options.PackageSources; + ChangeSettingsReturnedBySettingsProvider(); + packageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.AddFakePackageSource(packageSource); + var expectedSources = new List(); + expectedSources.Add(packageSource); + CloseSolution(); + + RegisteredPackageSources actualSources = options.PackageSources; + + Assert.AreEqual(expectedInitialSources, initialSources); + Assert.AreEqual(expectedSources, actualSources); + } + + [Test] + public void PackageSources_SolutionClosedAfterInitialPackageSourcesLoaded_ActivePackageSourceReloaded() + { + CreateSettings(); + var packageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.AddFakePackageSource(packageSource); + var expectedInitialSources = new List(); + expectedInitialSources.Add(packageSource); + var initialActivePackageSource = new PackageSource("http://nuget.org", "ProjectSource"); + fakeSettings.AddFakePackageSource(initialActivePackageSource); + fakeSettings.SetFakeActivePackageSource(initialActivePackageSource); + expectedInitialSources.Add(initialActivePackageSource); + OpenSolution(); + CreateOptions(fakeSettings); + RegisteredPackageSources actualInitialPackageSources = options.PackageSources; + PackageSource actualInitialActivePackageSource = options.ActivePackageSource; + ChangeSettingsReturnedBySettingsProvider(); + var expectedActivePackageSource = new PackageSource("http://codeplex.com", "Test"); + fakeSettings.SetFakeActivePackageSource(expectedActivePackageSource); + fakeSettings.AddFakePackageSource(expectedActivePackageSource); + CloseSolution(); + + PackageSource actualSource = options.ActivePackageSource; + + Assert.AreEqual(initialActivePackageSource, actualInitialActivePackageSource); + Assert.AreEqual(expectedActivePackageSource, actualSource); + Assert.AreEqual(expectedInitialSources, actualInitialPackageSources); + Assert.AreEqual(new PackageSource[] { expectedActivePackageSource }, options.PackageSources); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsViewModelTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsViewModelTests.cs index 87ec062600..12b6e35c5d 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsViewModelTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageManagementOptionsViewModelTests.cs @@ -50,8 +50,10 @@ namespace PackageManagement.Tests void CreateOptions() { var properties = new Properties(); + var projectService = new FakePackageManagementProjectService(); fakeSettings = new FakeSettings(); - options = new PackageManagementOptions(properties, fakeSettings); + SettingsProvider settingsProvider = TestablePackageManagementOptions.CreateSettingsProvider(fakeSettings, projectService); + options = new PackageManagementOptions(properties, settingsProvider); } void EnablePackageRestoreInOptions() diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs new file mode 100644 index 0000000000..cd5aab73b0 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs @@ -0,0 +1,80 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.PackageManagement; +using ICSharpCode.PackageManagement.Design; +using NuGet; +using NUnit.Framework; +using PackageManagement.Tests.Helpers; + +namespace PackageManagement.Tests +{ + [TestFixture] + public class SettingsProviderTests + { + SettingsProvider settingsProvider; + FakeSettings fakeSettings; + FakePackageManagementProjectService projectService; + IFileSystem fileSystemUsedToLoadSettings; + string configFileUsedToLoadSettings; + IMachineWideSettings machinesettingsUsedToLoadSettings; + + [SetUp] + public void SetUp() + { + fakeSettings = new FakeSettings(); + projectService = new FakePackageManagementProjectService(); + SettingsProvider.LoadDefaultSettings = LoadDefaultSettings; + settingsProvider = new SettingsProvider(projectService); + } + + ISettings LoadDefaultSettings(IFileSystem fileSystem, string configFile, IMachineWideSettings machineSettings) + { + fileSystemUsedToLoadSettings = fileSystem; + configFileUsedToLoadSettings = configFile; + machinesettingsUsedToLoadSettings = machineSettings; + + return fakeSettings; + } + + void OpenSolution(string fileName) + { + var helper = new SolutionHelper(fileName); + projectService.OpenSolution = helper.MSBuildSolution; + } + + [TearDown] + public void TearDown() + { + // This resets SettingsProvider.LoadDefaultSettings. + TestablePackageManagementOptions.CreateSettingsProvider(fakeSettings, projectService); + } + + [Test] + public void LoadSettings_NoSolutionOpen_NullFileSystemAndNullConfigFileAndNullMachineSettingsUsed() + { + fileSystemUsedToLoadSettings = new FakeFileSystem(); + configFileUsedToLoadSettings = "configFile"; + + ISettings settings = settingsProvider.LoadSettings(); + + Assert.IsNull(fileSystemUsedToLoadSettings); + Assert.IsNull(configFileUsedToLoadSettings); + Assert.IsNull(machinesettingsUsedToLoadSettings); + Assert.AreEqual(fakeSettings, settings); + } + + [Test] + public void LoadSettings_SolutionOpen_FileSystemWithRootSetToSolutionDirectoryUsedToLoadSettings() + { + string fileName = @"d:\projects\MyProject\MyProject.sln"; + OpenSolution(fileName); + + ISettings settings = settingsProvider.LoadSettings(); + + Assert.AreEqual(@"d:\projects\MyProject", fileSystemUsedToLoadSettings.Root); + Assert.AreEqual(fakeSettings, settings); + } + } +} From 50b2f02f0dd0a0a4157f97fecabd8f58112e0c8c Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 19 May 2014 19:03:29 +0100 Subject: [PATCH 14/15] Fix .nuget folder not being checked for a NuGet.Config file. --- .../Misc/PackageManagement/Project/Src/SettingsProvider.cs | 2 +- .../Misc/PackageManagement/Test/Src/SettingsProviderTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs b/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs index 016c27749e..7dfa1a5a25 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/SettingsProvider.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.PackageManagement { ISolution solution = projectService.OpenSolution; if (solution != null) { - return solution.Directory; + return Path.Combine(solution.Directory, ".nuget"); } return null; } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs index cd5aab73b0..10c2efd9fe 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/SettingsProviderTests.cs @@ -66,14 +66,14 @@ namespace PackageManagement.Tests } [Test] - public void LoadSettings_SolutionOpen_FileSystemWithRootSetToSolutionDirectoryUsedToLoadSettings() + public void LoadSettings_SolutionOpen_FileSystemWithRootSetToSolutionDotNuGetDirectoryUsedToLoadSettings() { string fileName = @"d:\projects\MyProject\MyProject.sln"; OpenSolution(fileName); ISettings settings = settingsProvider.LoadSettings(); - Assert.AreEqual(@"d:\projects\MyProject", fileSystemUsedToLoadSettings.Root); + Assert.AreEqual(@"d:\projects\MyProject\.nuget", fileSystemUsedToLoadSettings.Root); Assert.AreEqual(fakeSettings, settings); } } From 8384a172d60a4f4af11b3a6bf4d7156af30d0c8f Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Tue, 20 May 2014 20:50:05 +0100 Subject: [PATCH 15/15] Fix incorrect package sources being used when updating a package. On updating a package all the enabled package sources are used. On changing the enabled package sources, after opening a solution, the original set of enabled package sources were being still used. The change to support solution specific NuGet.Config files broke the original behaviour since the package sources are reloaded when a solution is opened or closed and the package repository cache was still using the original set of package sources. --- .../Project/Src/PackageManagementServices.cs | 2 +- .../Project/Src/PackageRepositoryCache.cs | 41 +++++++++++++------ .../Helpers/FakePackageRepositoryFactory.cs | 12 +++++- .../OneRegisteredPackageSourceHelper.cs | 8 ++-- .../TestablePackageManagementOptions.cs | 2 + .../Test/Src/PackageRepositoryCacheTests.cs | 38 +++++++++++++++-- 6 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs index 8a574eaa0e..a1fe7eb4f6 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementServices.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.PackageManagement static PackageManagementServices() { options = new PackageManagementOptions(); - packageRepositoryCache = new PackageRepositoryCache(options.PackageSources, options.RecentPackages); + packageRepositoryCache = new PackageRepositoryCache(options); userAgentGenerator = new UserAgentGeneratorForRepositoryRequests(packageRepositoryCache); registeredPackageRepositories = new RegisteredPackageRepositories(packageRepositoryCache, options); diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs index 72c2212373..3500715fd6 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageRepositoryCache.cs @@ -26,30 +26,36 @@ namespace ICSharpCode.PackageManagement public class PackageRepositoryCache : IPackageRepositoryCache, IPackageRepositoryFactoryEvents { ISharpDevelopPackageRepositoryFactory factory; - RegisteredPackageSources registeredPackageSources; + RegisteredPackageSources packageSources; + PackageManagementOptions options; IList recentPackages; IRecentPackageRepository recentPackageRepository; ConcurrentDictionary repositories = new ConcurrentDictionary(); public PackageRepositoryCache( - ISharpDevelopPackageRepositoryFactory factory, - RegisteredPackageSources registeredPackageSources, - IList recentPackages) + PackageManagementOptions options, + ISharpDevelopPackageRepositoryFactory factory) { + this.options = options; this.factory = factory; - this.registeredPackageSources = registeredPackageSources; - this.recentPackages = recentPackages; + this.recentPackages = options.RecentPackages; } - + + public PackageRepositoryCache(PackageManagementOptions options) + : this( + options, + new SharpDevelopPackageRepositoryFactory()) + { + } + public PackageRepositoryCache( - RegisteredPackageSources registeredPackageSources, + RegisteredPackageSources packageSources, IList recentPackages) - : this( - new SharpDevelopPackageRepositoryFactory(), - registeredPackageSources, - recentPackages) { + this.factory = new SharpDevelopPackageRepositoryFactory(); + this.recentPackages = recentPackages; + this.packageSources = packageSources; } public event EventHandler RepositoryCreated; @@ -102,10 +108,19 @@ namespace ICSharpCode.PackageManagement IEnumerable CreateAllEnabledRepositories() { - foreach (PackageSource source in registeredPackageSources.GetEnabledPackageSources()) { + foreach (PackageSource source in PackageSources.GetEnabledPackageSources()) { yield return CreateRepository(source.Source); } } + + RegisteredPackageSources PackageSources { + get { + if (packageSources != null) { + return packageSources; + } + return options.PackageSources; + } + } public IPackageRepository CreateAggregateRepository(IEnumerable repositories) { diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageRepositoryFactory.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageRepositoryFactory.cs index 1f5733638c..81e18deefa 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageRepositoryFactory.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/FakePackageRepositoryFactory.cs @@ -38,6 +38,13 @@ namespace PackageManagement.Tests.Helpers public Dictionary FakePackageRepositories = new Dictionary(); + public FakePackageRepositoryFactory() + { + CreateAggregrateRepositoryAction = (repositories) => { + return FakeAggregateRepository; + }; + } + public IPackageRepository CreateRepository(string packageSource) { PackageSourcesPassedToCreateRepository.Add(packageSource); @@ -84,16 +91,17 @@ namespace PackageManagement.Tests.Helpers } public IEnumerable RepositoriesPassedToCreateAggregateRepository; + public Func, IPackageRepository> CreateAggregrateRepositoryAction; public IPackageRepository CreateAggregateRepository(IEnumerable repositories) { RepositoriesPassedToCreateAggregateRepository = repositories; - return FakeAggregateRepository; + return CreateAggregrateRepositoryAction(repositories); } public FakePackageRepository AddFakePackageRepositoryForPackageSource(string source) { - var repository = new FakePackageRepository(); + var repository = new FakePackageRepository(); FakePackageRepositories.Add(source, repository); return repository; } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/OneRegisteredPackageSourceHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/OneRegisteredPackageSourceHelper.cs index 12d7da261c..f19e5545ed 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/OneRegisteredPackageSourceHelper.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/OneRegisteredPackageSourceHelper.cs @@ -26,11 +26,14 @@ namespace PackageManagement.Tests.Helpers { public class OneRegisteredPackageSourceHelper { - public RegisteredPackageSources RegisteredPackageSources; public TestablePackageManagementOptions Options; public FakeSettings FakeSettings; public PackageSource PackageSource = new PackageSource("http://sharpdevelop.com", "Test Package Source"); + public RegisteredPackageSources RegisteredPackageSources { + get { return Options.PackageSources; } + } + public OneRegisteredPackageSourceHelper() { CreateOneRegisteredPackageSource(); @@ -41,7 +44,6 @@ namespace PackageManagement.Tests.Helpers Properties properties = new Properties(); Options = new TestablePackageManagementOptions(); FakeSettings = Options.FakeSettings; - RegisteredPackageSources = Options.PackageSources; AddOnePackageSource(); } @@ -58,7 +60,7 @@ namespace PackageManagement.Tests.Helpers } public void AddTwoPackageSources() - { + { AddOnePackageSource(); var packageSource = new PackageSource("http://second.codeplex.com", "second"); RegisteredPackageSources.Add(packageSource); diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs index 2f415b5ad8..c892b9f3b7 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/TestablePackageManagementOptions.cs @@ -27,6 +27,7 @@ namespace PackageManagement.Tests.Helpers { public Properties Properties; public FakeSettings FakeSettings; + public FakePackageManagementProjectService ProjectService; public TestablePackageManagementOptions() : this(new Properties(), new FakeSettings(), new FakePackageManagementProjectService()) @@ -41,6 +42,7 @@ namespace PackageManagement.Tests.Helpers { this.Properties = properties; this.FakeSettings = fakeSettings; + this.ProjectService = projectService; } public static void ChangeSettingsReturnedBySettingsProvider(FakeSettings settings) diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs index d559526161..0c33e09728 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/PackageRepositoryCacheTests.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.IO.Packaging; +using System.Linq; using ICSharpCode.PackageManagement; using ICSharpCode.PackageManagement.Design; using NuGet; @@ -52,9 +53,7 @@ namespace PackageManagement.Tests { nuGetPackageSource = new PackageSource("http://nuget.org", "NuGet"); fakePackageRepositoryFactory = new FakePackageRepositoryFactory(); - RegisteredPackageSources packageSources = packageSourcesHelper.Options.PackageSources; - IList recentPackages = packageSourcesHelper.Options.RecentPackages; - cache = new PackageRepositoryCache(fakePackageRepositoryFactory, packageSources, recentPackages); + cache = new PackageRepositoryCache(packageSourcesHelper.Options, fakePackageRepositoryFactory); } FakePackageRepository AddFakePackageRepositoryForPackageSource(string source) @@ -395,5 +394,38 @@ namespace PackageManagement.Tests Assert.IsNull(eventArgs); } + + [Test] + public void CreateAggregateRepository_SolutionClosedAndEnabledPackageSourcesChangedAfterCacheCreated_AggregateRepositoryContainsCorrectEnabledPackageRepositories() + { + CreatePackageSources(); + packageSourcesHelper.AddTwoPackageSources("Source1", "Source2"); + CreateCacheUsingPackageSources(); + FakePackageRepository source1Repo = AddFakePackageRepositoryForPackageSource("Source1"); + FakePackageRepository source2Repo = AddFakePackageRepositoryForPackageSource("Source2"); + fakePackageRepositoryFactory.CreateAggregrateRepositoryAction = (repositories) => { + return new AggregateRepository (repositories); + }; + var initialAggregateRepository = cache.CreateAggregateRepository() as AggregateRepository; + var expectedInitialRepositories = new FakePackageRepository[] { + source1Repo, + source2Repo + }; + List actualInitialRepositories = initialAggregateRepository.Repositories.ToList(); + var solution = new SolutionHelper().MSBuildSolution; + packageSourcesHelper.Options.ProjectService.FireSolutionClosedEvent(solution); + packageSourcesHelper.Options.PackageSources.Clear(); + packageSourcesHelper.Options.PackageSources.Add(new PackageSource ("Source3")); + FakePackageRepository source3Repo = AddFakePackageRepositoryForPackageSource("Source3"); + var expectedRepositories = new FakePackageRepository[] { + source3Repo + }; + + var aggregateRepository = cache.CreateAggregateRepository() as AggregateRepository; + List actualRepositories = aggregateRepository.Repositories.ToList(); + + CollectionAssert.AreEqual(expectedInitialRepositories, actualInitialRepositories); + CollectionAssert.AreEqual(expectedRepositories, actualRepositories); + } } }