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 15 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; @@ -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 @@ -23,6 +24,27 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
[ExtensionFor(typeof(ContentControl))]
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()
{
base.OnInitialized();
@ -83,6 +105,12 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -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;

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

@ -27,6 +27,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -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
{
/// <summary/>

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

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

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

@ -9,7 +9,8 @@ using System.Collections.Generic; @@ -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 @@ -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.
/// </summary>
public class XamlEditOperations
{
readonly XamlDesignContext _context;
readonly XamlParserSettings _settings;
/// <summary>
/// Delimet character to seperate different piece of Xaml's
/// </summary>
readonly char _delimeter = Convert.ToChar(0x7F);
{
readonly XamlDesignContext _context;
readonly XamlParserSettings _settings;
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)
{
this._context = context;
this._settings = settings;
}
/// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary>
public void Cut(ICollection<DesignItem> 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();
}
/// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary>
public void Copy(ICollection<DesignItem> 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();
}
/// <summary>
/// Paste items from clipboard into the designer.
/// </summary>
public void Paste()
{
bool pasted = false;
string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml);
IEnumerable<string> xamls = combinedXaml.Split(_delimeter);
xamls = xamls.Where(xaml => xaml != "");
public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings)
{
this._context = context;
this._settings = settings;
}
/// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary>
public void Cut(ICollection<DesignItem> 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();
}
/// <summary>
/// Copy <paramref name="designItems"/> from the designer to clipboard.
/// </summary>
public void Copy(ICollection<DesignItem> 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();
}
/// <summary>
/// Paste items from clipboard into the designer.
/// </summary>
public void Paste()
{
bool pasted = false;
string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml);
IEnumerable<string> 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<DesignItem>();
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<DesignItem>();
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<IPlacementBehavior>()!=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();
}
}
/// <summary>
/// Adds Items under a parent given that the content property is collection and can add types of <paramref name="pastedItems"/>
/// </summary>
/// <param name="parent">The Parent element</param>
/// <param name="pastedItems">The list of elements to be added</param>
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)));
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();
}
}
/// <summary>
/// Adds Items under a parent given that the content property is collection and can add types of <paramref name="pastedItems"/>
/// </summary>
/// <param name="parent">The Parent element</param>
/// <param name="pastedItems">The list of elements to be added</param>
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)));
var operation = PlacementOperation.TryStartInsertNewComponents(parent, pastedItems, rects.ToList(), PlacementType.AddItem);
ISelectionService selection = _context.Services.Selection;
selection.SetSelectedComponents(pastedItems);
if(operation!=null)
operation.Commit();
}
}
}

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

@ -0,0 +1,120 @@ @@ -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 @@ @@ -55,6 +55,7 @@
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Designer\EditOperationTests.cs" />
<Compile Include="Designer\FocusNavigatorTests.cs" />
<Compile Include="Designer\MarginHandleTests.cs" />
<Compile Include="Designer\MockFocusNavigator.cs" />

Loading…
Cancel
Save