Browse Source

- 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
pull/1/head
Kumar Devvrat 16 years ago
parent
commit
e22ed87a60
  1. 28
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs
  2. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs
  3. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
  4. 295
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs
  5. 120
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs
  6. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/WpfDesign.Tests.csproj

28
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs

@ -16,6 +16,7 @@ using ICSharpCode.WpfDesign.Designer.Controls;
using System.Diagnostics; using System.Diagnostics;
using ICSharpCode.WpfDesign.XamlDom; using ICSharpCode.WpfDesign.XamlDom;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Controls.Primitives;
namespace ICSharpCode.WpfDesign.Designer.Extensions namespace ICSharpCode.WpfDesign.Designer.Extensions
{ {
@ -23,6 +24,27 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
[ExtensionFor(typeof(ContentControl))] [ExtensionFor(typeof(ContentControl))]
public class DefaultPlacementBehavior : BehaviorExtension, IPlacementBehavior public class DefaultPlacementBehavior : BehaviorExtension, IPlacementBehavior
{ {
static List<Type> _contentControlsNotAllowedToAdd;
static DefaultPlacementBehavior()
{
_contentControlsNotAllowedToAdd = new List<Type>();
_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() protected override void OnInitialized()
{ {
base.OnInitialized(); base.OnInitialized();
@ -83,6 +105,12 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
if (ExtendedItem.ContentProperty.IsCollection) if (ExtendedItem.ContentProperty.IsCollection)
return CollectionSupport.CanCollectionAdd(ExtendedItem.ContentProperty.ReturnType, return CollectionSupport.CanCollectionAdd(ExtendedItem.ContentProperty.ReturnType,
operation.PlacedItems.Select(p => p.Item.Component)); operation.PlacedItems.Select(p => p.Item.Component));
if (ExtendedItem.View is ContentControl) {
if (!CanContentControlAdd((ContentControl) ExtendedItem.View)) {
return false;
}
}
if (!ExtendedItem.ContentProperty.IsSet) if (!ExtendedItem.ContentProperty.IsSet)
return true; return true;

1
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
[ExtensionFor(typeof(Panel))] [ExtensionFor(typeof(Panel))]
[ExtensionFor(typeof(Image))] [ExtensionFor(typeof(Image))]
[ExtensionFor(typeof(MediaElement))] [ExtensionFor(typeof(MediaElement))]
[ExtensionFor(typeof(ItemsControl))]
public class TopLeftContainerDragHandle : AdornerProvider public class TopLeftContainerDragHandle : AdornerProvider
{ {
/// <summary/> /// <summary/>

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
readonly XamlEditOperations _xamlEditOperations; readonly XamlEditOperations _xamlEditOperations;
internal XamlEditOperations XamlEditAction { public XamlEditOperations XamlEditAction {
get { return _xamlEditOperations; } get { return _xamlEditOperations; }
} }

295
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs

@ -9,7 +9,8 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using ICSharpCode.WpfDesign.Designer.Extensions;
using ICSharpCode.WpfDesign.XamlDom; using ICSharpCode.WpfDesign.XamlDom;
namespace ICSharpCode.WpfDesign.Designer.Xaml 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. /// Deals with operations on controls which also require access to internal XML properties of the XAML Document.
/// </summary> /// </summary>
public class XamlEditOperations public class XamlEditOperations
{ {
readonly XamlDesignContext _context; readonly XamlDesignContext _context;
readonly XamlParserSettings _settings; readonly XamlParserSettings _settings;
/// <summary>
/// Delimet character to seperate different piece of Xaml's readonly char _delimeter = Convert.ToChar(0x7F);
/// </summary>
readonly char _delimeter = Convert.ToChar(0x7F); /// <summary>
/// Delimet character to seperate different piece of Xaml's
/// </summary>
public char Delimeter {
get { return _delimeter; }
}
public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings) public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings)
{ {
this._context = context; this._context = context;
this._settings = settings; this._settings = settings;
} }
/// <summary> /// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard. /// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary> /// </summary>
public void Cut(ICollection<DesignItem> designItems) public void Cut(ICollection<DesignItem> designItems)
{ {
Clipboard.Clear(); Clipboard.Clear();
string cutXaml = ""; string cutXaml = "";
var changeGroup = _context.OpenGroup("Cut " + designItems.Count + " elements", designItems); var changeGroup = _context.OpenGroup("Cut " + designItems.Count + " elements", designItems);
foreach (var item in designItems) foreach (var item in designItems)
{ {
if (item != null && item != _context.RootItem) if (item != null && item != _context.RootItem)
{ {
XamlDesignItem xamlItem = item as XamlDesignItem; XamlDesignItem xamlItem = item as XamlDesignItem;
if (xamlItem != null) { if (xamlItem != null) {
cutXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); cutXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject);
cutXaml += _delimeter; cutXaml += _delimeter;
} }
} }
} }
ModelTools.DeleteComponents(designItems); ModelTools.DeleteComponents(designItems);
Clipboard.SetText(cutXaml, TextDataFormat.Xaml); Clipboard.SetText(cutXaml, TextDataFormat.Xaml);
changeGroup.Commit(); changeGroup.Commit();
} }
/// <summary> /// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard. /// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary> /// </summary>
public void Copy(ICollection<DesignItem> designItems) public void Copy(ICollection<DesignItem> designItems)
{ {
Clipboard.Clear(); Clipboard.Clear();
string copiedXaml = ""; string copiedXaml = "";
var changeGroup = _context.OpenGroup("Copy " + designItems.Count + " elements", designItems); var changeGroup = _context.OpenGroup("Copy " + designItems.Count + " elements", designItems);
foreach (var item in designItems) foreach (var item in designItems)
{ {
if (item != null) if (item != null)
{ {
XamlDesignItem xamlItem = item as XamlDesignItem; XamlDesignItem xamlItem = item as XamlDesignItem;
if (xamlItem != null) { if (xamlItem != null) {
copiedXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); copiedXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject);
copiedXaml += _delimeter; copiedXaml += _delimeter;
} }
} }
} }
Clipboard.SetText(copiedXaml, TextDataFormat.Xaml); Clipboard.SetText(copiedXaml, TextDataFormat.Xaml);
changeGroup.Commit(); changeGroup.Commit();
} }
/// <summary> /// <summary>
/// Paste items from clipboard into the designer. /// Paste items from clipboard into the designer.
/// </summary> /// </summary>
public void Paste() public void Paste()
{ {
bool pasted = false; bool pasted = false;
string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml); string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml);
IEnumerable<string> xamls = combinedXaml.Split(_delimeter); IEnumerable<string> xamls = combinedXaml.Split(_delimeter);
xamls = xamls.Where(xaml => xaml != ""); xamls = xamls.Where(xaml => xaml != "");
DesignItem parent = _context.Services.Selection.PrimarySelection; DesignItem parent = _context.Services.Selection.PrimarySelection;
DesignItem child = _context.Services.Selection.PrimarySelection; DesignItem child = _context.Services.Selection.PrimarySelection;
XamlDesignItem rootItem = _context.RootItem as XamlDesignItem; XamlDesignItem rootItem = _context.RootItem as XamlDesignItem;
var pastedItems = new Collection<DesignItem>(); var pastedItems = new Collection<DesignItem>();
foreach(var xaml in xamls) { foreach(var xaml in xamls) {
var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, _settings); var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, _settings);
if(obj!=null) { if(obj!=null) {
DesignItem item = _context._componentService.RegisterXamlComponentRecursive(obj); DesignItem item = _context._componentService.RegisterXamlComponentRecursive(obj);
if (item != null) if (item != null)
pastedItems.Add(item); pastedItems.Add(item);
} }
} }
if (pastedItems.Count != 0) { if (pastedItems.Count != 0) {
var changeGroup = _context.OpenGroup("Paste " + pastedItems.Count + " elements", pastedItems); var changeGroup = _context.OpenGroup("Paste " + pastedItems.Count + " elements", pastedItems);
while (parent != null && pasted == false) { while (parent != null && pasted == false) {
if (parent.ContentProperty != null) { if (parent.ContentProperty != null) {
if (parent.ContentProperty.IsCollection) { if (parent.ContentProperty.IsCollection) {
if (CollectionSupport.CanCollectionAdd(parent.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { if (CollectionSupport.CanCollectionAdd(parent.ContentProperty.ReturnType, pastedItems.Select(item => item.Component)) && parent.GetBehavior<IPlacementBehavior>()!=null) {
AddInParent(parent, pastedItems); AddInParent(parent, pastedItems);
pasted = true; pasted = true;
} }
} else if (pastedItems.Count == 1 && parent.ContentProperty.Value == null && parent.ContentProperty.ValueOnInstance == null) { } else if (pastedItems.Count == 1 && parent.ContentProperty.Value == null && parent.ContentProperty.ValueOnInstance == null && DefaultPlacementBehavior.CanContentControlAdd((ContentControl)parent.View)) {
AddInParent(parent, pastedItems); AddInParent(parent, pastedItems);
pasted = true; pasted = true;
} else { }
parent = parent.Parent; if(!pasted)
} parent=parent.Parent;
} else { } else {
parent = parent.Parent; parent = parent.Parent;
} }
} }
while (pasted == false) { while (pasted == false) {
if (child.ContentProperty != null) { if (child.ContentProperty != null) {
if (child.ContentProperty.IsCollection) { if (child.ContentProperty.IsCollection) {
foreach (var col in child.ContentProperty.CollectionElements) { foreach (var col in child.ContentProperty.CollectionElements) {
if (col.ContentProperty != null && col.ContentProperty.IsCollection) { if (col.ContentProperty != null && col.ContentProperty.IsCollection) {
if (CollectionSupport.CanCollectionAdd(col.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { if (CollectionSupport.CanCollectionAdd(col.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) {
pasted = true; pasted = true;
} }
} }
} }
break; break;
} else if (child.ContentProperty.Value != null) { } else if (child.ContentProperty.Value != null) {
child = child.ContentProperty.Value; child = child.ContentProperty.Value;
} else if (pastedItems.Count == 1) { } else if (pastedItems.Count == 1) {
child.ContentProperty.SetValue(pastedItems.First().Component); child.ContentProperty.SetValue(pastedItems.First().Component);
pasted = true; pasted = true;
break; break;
} else } else
break; break;
} else } else
break; break;
} }
changeGroup.Commit(); changeGroup.Commit();
} }
} }
/// <summary> /// <summary>
/// Adds Items under a parent given that the content property is collection and can add types of <paramref name="pastedItems"/> /// Adds Items under a parent given that the content property is collection and can add types of <paramref name="pastedItems"/>
/// </summary> /// </summary>
/// <param name="parent">The Parent element</param> /// <param name="parent">The Parent element</param>
/// <param name="pastedItems">The list of elements to be added</param> /// <param name="pastedItems">The list of elements to be added</param>
void AddInParent(DesignItem parent,IList<DesignItem> pastedItems) void AddInParent(DesignItem parent,IList<DesignItem> pastedItems)
{ {
IEnumerable<Rect> rects = pastedItems.Select(i => new Rect(new Point(0, 0), new Point((double)i.Properties["Width"].ValueOnInstance, (double)i.Properties["Height"].ValueOnInstance))); IEnumerable<Rect> 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); var operation = PlacementOperation.TryStartInsertNewComponents(parent, pastedItems, rects.ToList(), PlacementType.AddItem);
ISelectionService selection = _context.Services.Selection; ISelectionService selection = _context.Services.Selection;
selection.SetSelectedComponents(pastedItems); selection.SetSelectedComponents(pastedItems);
operation.Commit(); if(operation!=null)
} operation.Commit();
} }
}
} }

120
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/EditOperationTests.cs

@ -0,0 +1,120 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Kumar Devvrat"/>
// <version>$Revision: $</version>
// </file>
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("<Button/><Button/>");
var xamlContext = grid.Context as XamlDesignContext;
if (xamlContext != null) {
xamlContext.XamlEditAction.Cut(grid.ContentProperty.CollectionElements);
var cutXaml = Clipboard.GetText(TextDataFormat.Xaml);
Assert.AreEqual("<Buttonxmlns=\"" + XamlConstants.PresentationNamespace + "\"/>" + xamlContext.XamlEditAction.Delimeter + "<Buttonxmlns=\"" + XamlConstants.PresentationNamespace + "\"/>" + xamlContext.XamlEditAction.Delimeter, cutXaml.Replace(" ", ""));
Assert.AreEqual(0, grid.ContentProperty.CollectionElements.Count);
} else {
Assert.Fail();
}
}
[Test]
public void Copy()
{
var grid = CreateGridContextWithDesignSurface("<Button/><Button/>");
var xamlContext = grid.Context as XamlDesignContext;
if (xamlContext != null) {
xamlContext.XamlEditAction.Copy(grid.ContentProperty.CollectionElements);
var cutXaml = Clipboard.GetText(TextDataFormat.Xaml);
Assert.AreEqual("<Buttonxmlns=\"" + XamlConstants.PresentationNamespace + "\"/>" + xamlContext.XamlEditAction.Delimeter + "<Buttonxmlns=\"" + XamlConstants.PresentationNamespace + "\"/>" + xamlContext.XamlEditAction.Delimeter, cutXaml.Replace(" ", ""));
Assert.AreEqual(2, grid.ContentProperty.CollectionElements.Count);
} else {
Assert.Fail();
}
}
private string _name;
private DesignItem IntializePasteOperationsTest()
{
var grid = CreateGridContextWithDesignSurface("<Button Name=\"TestElement\"/><Grid><Button/></Grid><Window/><ListBox/>");
Assert.IsNotNull(grid);
var xamlConxtext = grid.Context as XamlDesignContext;
if (xamlConxtext != null) {
_name = grid.ContentProperty.CollectionElements[0].Name;
xamlConxtext.XamlEditAction.Cut(new[] {grid.ContentProperty.CollectionElements[0]});
} else
Assert.Fail();
return grid;
}
[Test]
public void PasteWhenContentControlSelectedAndCannotAdd()
{
var grid = IntializePasteOperationsTest();
var xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
var selection = grid.Services.Selection;
var innerGrid = grid.ContentProperty.CollectionElements[0];
selection.SetSelectedComponents(innerGrid.ContentProperty.CollectionElements);
xamlContext.XamlEditAction.Paste();
Assert.AreEqual(_name, innerGrid.ContentProperty.CollectionElements[1].Name);
Assert.AreEqual(innerGrid.ContentProperty.CollectionElements[1], selection.PrimarySelection);
}
[Test]
public void PasteWhenContentControlSelectedAndCanAdd()
{
var grid = IntializePasteOperationsTest();
var xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
var selection = grid.Services.Selection;
var window = grid.ContentProperty.CollectionElements[1];
selection.SetSelectedComponents(new[] {window});
xamlContext.XamlEditAction.Paste();
Assert.AreEqual(_name, window.ContentProperty.Value.Name);
Assert.AreEqual(window.ContentProperty.Value, selection.PrimarySelection);
}
[Test]
public void PasteWhenIAddChildSelectedAndCanAdd()
{
var grid = IntializePasteOperationsTest();
var xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] {grid});
xamlContext.XamlEditAction.Paste();
Assert.AreEqual(_name, grid.ContentProperty.CollectionElements[3].Name);
Assert.AreEqual(grid.ContentProperty.CollectionElements[3], selection.PrimarySelection);
}
[Test]
public void PasteWhenIAddChildSelectedAndCannotAdd()
{
var grid = IntializePasteOperationsTest();
var xamlContext = grid.Context as XamlDesignContext;
Assert.IsNotNull(xamlContext);
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] {grid.ContentProperty.CollectionElements[2]});
xamlContext.XamlEditAction.Paste();
Assert.AreEqual(_name, grid.ContentProperty.CollectionElements[3].Name);
Assert.AreEqual(grid.ContentProperty.CollectionElements[3], selection.PrimarySelection);
}
}
}

1
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/WpfDesign.Tests.csproj

@ -55,6 +55,7 @@
<Link>GlobalAssemblyInfo.cs</Link> <Link>GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyInfo.cs" />
<Compile Include="Designer\EditOperationTests.cs" />
<Compile Include="Designer\FocusNavigatorTests.cs" /> <Compile Include="Designer\FocusNavigatorTests.cs" />
<Compile Include="Designer\MarginHandleTests.cs" /> <Compile Include="Designer\MarginHandleTests.cs" />
<Compile Include="Designer\MockFocusNavigator.cs" /> <Compile Include="Designer\MockFocusNavigator.cs" />

Loading…
Cancel
Save