From e22ed87a60661dfb006b046e3a746ef5b8c4d4b4 Mon Sep 17 00:00:00 2001 From: Kumar Devvrat Date: Tue, 10 Aug 2010 22:48:43 +0000 Subject: [PATCH] - Fix a bug which caused a ContentControl to be placed inside another ContentControl when it should not be. - Add tests for edit operations and fix existing bugs in there. - Extend container drag handle for ItemsControl. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6402 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Extensions/DefaultPlacementBehavior.cs | 28 ++ .../Extensions/TopLeftContainerDragHandle.cs | 1 + .../Project/Xaml/XamlDesignContext.cs | 2 +- .../Project/Xaml/XamlEditOperations.cs | 295 +++++++++--------- .../Tests/Designer/EditOperationTests.cs | 120 +++++++ .../Tests/WpfDesign.Tests.csproj | 1 + 6 files changed, 302 insertions(+), 145 deletions(-) create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs index f2698314b6..4af8cd1513 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs @@ -16,6 +16,7 @@ using ICSharpCode.WpfDesign.Designer.Controls; using System.Diagnostics; using ICSharpCode.WpfDesign.XamlDom; using System.Windows.Media; +using System.Windows.Controls.Primitives; namespace ICSharpCode.WpfDesign.Designer.Extensions { @@ -23,6 +24,27 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions [ExtensionFor(typeof(ContentControl))] public class DefaultPlacementBehavior : BehaviorExtension, IPlacementBehavior { + static List _contentControlsNotAllowedToAdd; + + static DefaultPlacementBehavior() + { + _contentControlsNotAllowedToAdd = new List(); + _contentControlsNotAllowedToAdd.Add(typeof (Frame)); + _contentControlsNotAllowedToAdd.Add(typeof (GroupItem)); + _contentControlsNotAllowedToAdd.Add(typeof (HeaderedContentControl)); + _contentControlsNotAllowedToAdd.Add(typeof (Label)); + _contentControlsNotAllowedToAdd.Add(typeof (ListBoxItem)); + _contentControlsNotAllowedToAdd.Add(typeof (ButtonBase)); + _contentControlsNotAllowedToAdd.Add(typeof (StatusBarItem)); + _contentControlsNotAllowedToAdd.Add(typeof (ToolTip)); + } + + public static bool CanContentControlAdd(ContentControl control) + { + Debug.Assert(control != null); + return !_contentControlsNotAllowedToAdd.Any(type => type.IsAssignableFrom(control.GetType())); + } + protected override void OnInitialized() { base.OnInitialized(); @@ -83,6 +105,12 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (ExtendedItem.ContentProperty.IsCollection) return CollectionSupport.CanCollectionAdd(ExtendedItem.ContentProperty.ReturnType, operation.PlacedItems.Select(p => p.Item.Component)); + if (ExtendedItem.View is ContentControl) { + if (!CanContentControlAdd((ContentControl) ExtendedItem.View)) { + return false; + } + } + if (!ExtendedItem.ContentProperty.IsSet) return true; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs index 1fd1078121..c5438324da 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions [ExtensionFor(typeof(Panel))] [ExtensionFor(typeof(Image))] [ExtensionFor(typeof(MediaElement))] + [ExtensionFor(typeof(ItemsControl))] public class TopLeftContainerDragHandle : AdornerProvider { /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs index 54dc9f2342..56a7e30649 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml readonly XamlEditOperations _xamlEditOperations; - internal XamlEditOperations XamlEditAction { + public XamlEditOperations XamlEditAction { get { return _xamlEditOperations; } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs index 34befdebfc..b3638f2687 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs @@ -9,7 +9,8 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Windows; - +using System.Windows.Controls; +using ICSharpCode.WpfDesign.Designer.Extensions; using ICSharpCode.WpfDesign.XamlDom; namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -18,150 +19,156 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml /// Deals with operations on controls which also require access to internal XML properties of the XAML Document. /// public class XamlEditOperations - { - readonly XamlDesignContext _context; - readonly XamlParserSettings _settings; - - /// - /// Delimet character to seperate different piece of Xaml's - /// - readonly char _delimeter = Convert.ToChar(0x7F); + { + readonly XamlDesignContext _context; + readonly XamlParserSettings _settings; + + + readonly char _delimeter = Convert.ToChar(0x7F); + + /// + /// Delimet character to seperate different piece of Xaml's + /// + public char Delimeter { + get { return _delimeter; } + } - public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings) - { - this._context = context; - this._settings = settings; - } - - /// - /// Copy from the designer to clipboard. - /// - public void Cut(ICollection designItems) - { - Clipboard.Clear(); - string cutXaml = ""; - var changeGroup = _context.OpenGroup("Cut " + designItems.Count + " elements", designItems); - foreach (var item in designItems) - { - if (item != null && item != _context.RootItem) - { - XamlDesignItem xamlItem = item as XamlDesignItem; - if (xamlItem != null) { - cutXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); - cutXaml += _delimeter; - } - } - } - ModelTools.DeleteComponents(designItems); - Clipboard.SetText(cutXaml, TextDataFormat.Xaml); - changeGroup.Commit(); - } - - /// - /// Copy from the designer to clipboard. - /// - public void Copy(ICollection designItems) - { - Clipboard.Clear(); - string copiedXaml = ""; - var changeGroup = _context.OpenGroup("Copy " + designItems.Count + " elements", designItems); - foreach (var item in designItems) - { - if (item != null) - { - XamlDesignItem xamlItem = item as XamlDesignItem; - if (xamlItem != null) { - copiedXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); - copiedXaml += _delimeter; - } - } - } - Clipboard.SetText(copiedXaml, TextDataFormat.Xaml); - changeGroup.Commit(); - } - - /// - /// Paste items from clipboard into the designer. - /// - public void Paste() - { - bool pasted = false; - string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml); - IEnumerable xamls = combinedXaml.Split(_delimeter); - xamls = xamls.Where(xaml => xaml != ""); + public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings) + { + this._context = context; + this._settings = settings; + } + + /// + /// Copy from the designer to clipboard. + /// + public void Cut(ICollection designItems) + { + Clipboard.Clear(); + string cutXaml = ""; + var changeGroup = _context.OpenGroup("Cut " + designItems.Count + " elements", designItems); + foreach (var item in designItems) + { + if (item != null && item != _context.RootItem) + { + XamlDesignItem xamlItem = item as XamlDesignItem; + if (xamlItem != null) { + cutXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); + cutXaml += _delimeter; + } + } + } + ModelTools.DeleteComponents(designItems); + Clipboard.SetText(cutXaml, TextDataFormat.Xaml); + changeGroup.Commit(); + } + + /// + /// Copy from the designer to clipboard. + /// + public void Copy(ICollection designItems) + { + Clipboard.Clear(); + string copiedXaml = ""; + var changeGroup = _context.OpenGroup("Copy " + designItems.Count + " elements", designItems); + foreach (var item in designItems) + { + if (item != null) + { + XamlDesignItem xamlItem = item as XamlDesignItem; + if (xamlItem != null) { + copiedXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); + copiedXaml += _delimeter; + } + } + } + Clipboard.SetText(copiedXaml, TextDataFormat.Xaml); + changeGroup.Commit(); + } + + /// + /// Paste items from clipboard into the designer. + /// + public void Paste() + { + bool pasted = false; + string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml); + IEnumerable xamls = combinedXaml.Split(_delimeter); + xamls = xamls.Where(xaml => xaml != ""); - DesignItem parent = _context.Services.Selection.PrimarySelection; - DesignItem child = _context.Services.Selection.PrimarySelection; - - XamlDesignItem rootItem = _context.RootItem as XamlDesignItem; - var pastedItems = new Collection(); - foreach(var xaml in xamls) { - var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, _settings); - if(obj!=null) { - DesignItem item = _context._componentService.RegisterXamlComponentRecursive(obj); - if (item != null) - pastedItems.Add(item); - } - } - - if (pastedItems.Count != 0) { - var changeGroup = _context.OpenGroup("Paste " + pastedItems.Count + " elements", pastedItems); - while (parent != null && pasted == false) { - if (parent.ContentProperty != null) { - if (parent.ContentProperty.IsCollection) { - if (CollectionSupport.CanCollectionAdd(parent.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { - AddInParent(parent, pastedItems); - pasted = true; - } - } else if (pastedItems.Count == 1 && parent.ContentProperty.Value == null && parent.ContentProperty.ValueOnInstance == null) { - AddInParent(parent, pastedItems); - pasted = true; - } else { - parent = parent.Parent; - } - } else { - parent = parent.Parent; - } - } + DesignItem parent = _context.Services.Selection.PrimarySelection; + DesignItem child = _context.Services.Selection.PrimarySelection; + + XamlDesignItem rootItem = _context.RootItem as XamlDesignItem; + var pastedItems = new Collection(); + foreach(var xaml in xamls) { + var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, _settings); + if(obj!=null) { + DesignItem item = _context._componentService.RegisterXamlComponentRecursive(obj); + if (item != null) + pastedItems.Add(item); + } + } + + if (pastedItems.Count != 0) { + var changeGroup = _context.OpenGroup("Paste " + pastedItems.Count + " elements", pastedItems); + while (parent != null && pasted == false) { + if (parent.ContentProperty != null) { + if (parent.ContentProperty.IsCollection) { + if (CollectionSupport.CanCollectionAdd(parent.ContentProperty.ReturnType, pastedItems.Select(item => item.Component)) && parent.GetBehavior()!=null) { + AddInParent(parent, pastedItems); + pasted = true; + } + } else if (pastedItems.Count == 1 && parent.ContentProperty.Value == null && parent.ContentProperty.ValueOnInstance == null && DefaultPlacementBehavior.CanContentControlAdd((ContentControl)parent.View)) { + AddInParent(parent, pastedItems); + pasted = true; + } + if(!pasted) + parent=parent.Parent; + } else { + parent = parent.Parent; + } + } - while (pasted == false) { - if (child.ContentProperty != null) { - if (child.ContentProperty.IsCollection) { - foreach (var col in child.ContentProperty.CollectionElements) { - if (col.ContentProperty != null && col.ContentProperty.IsCollection) { - if (CollectionSupport.CanCollectionAdd(col.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { - pasted = true; - } - } - } - break; - } else if (child.ContentProperty.Value != null) { - child = child.ContentProperty.Value; - } else if (pastedItems.Count == 1) { - child.ContentProperty.SetValue(pastedItems.First().Component); - pasted = true; - break; - } else - break; - } else - break; - } - changeGroup.Commit(); - } - } - - /// - /// Adds Items under a parent given that the content property is collection and can add types of - /// - /// The Parent element - /// The list of elements to be added - void AddInParent(DesignItem parent,IList pastedItems) - { - IEnumerable rects = pastedItems.Select(i => new Rect(new Point(0, 0), new Point((double)i.Properties["Width"].ValueOnInstance, (double)i.Properties["Height"].ValueOnInstance))); - var operation = PlacementOperation.TryStartInsertNewComponents(parent, pastedItems, rects.ToList(), PlacementType.AddItem); - ISelectionService selection = _context.Services.Selection; - selection.SetSelectedComponents(pastedItems); - operation.Commit(); - } - } + while (pasted == false) { + if (child.ContentProperty != null) { + if (child.ContentProperty.IsCollection) { + foreach (var col in child.ContentProperty.CollectionElements) { + if (col.ContentProperty != null && col.ContentProperty.IsCollection) { + if (CollectionSupport.CanCollectionAdd(col.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { + pasted = true; + } + } + } + break; + } else if (child.ContentProperty.Value != null) { + child = child.ContentProperty.Value; + } else if (pastedItems.Count == 1) { + child.ContentProperty.SetValue(pastedItems.First().Component); + pasted = true; + break; + } else + break; + } else + break; + } + changeGroup.Commit(); + } + } + + /// + /// Adds Items under a parent given that the content property is collection and can add types of + /// + /// The Parent element + /// The list of elements to be added + void AddInParent(DesignItem parent,IList pastedItems) + { + IEnumerable rects = pastedItems.Select(i => new Rect(new Point(0, 0), new Point((double)i.Properties["Width"].ValueOnInstance, (double)i.Properties["Height"].ValueOnInstance))); + var operation = PlacementOperation.TryStartInsertNewComponents(parent, pastedItems, rects.ToList(), PlacementType.AddItem); + ISelectionService selection = _context.Services.Selection; + selection.SetSelectedComponents(pastedItems); + if(operation!=null) + operation.Commit(); + } + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs new file mode 100644 index 0000000000..86ef47fdf6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs @@ -0,0 +1,120 @@ +// +// +// +// +// $Revision: $ +// +using System.Windows; +using NUnit.Framework; +using ICSharpCode.WpfDesign.Designer.Xaml; +using ICSharpCode.WpfDesign.XamlDom; + +namespace ICSharpCode.WpfDesign.Tests.Designer +{ + [TestFixture] + public class EditOperationTests : ModelTestHelper + { + [Test] + public void Cut() + { + var grid = CreateGridContextWithDesignSurface("