Browse Source

Begin work on moving components between containers.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2417 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
a6e2f1476d
  1. 4
      src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
  2. 29
      src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
  3. 9
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs
  4. 39
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs
  5. 107
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs
  6. 48
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs
  7. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs
  8. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
  9. 105
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/WindowResizeBehavior.cs
  10. 51
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs
  11. 22
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/OptionService.cs
  12. 3
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
  13. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
  14. 8
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs
  15. 77
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelCollectionElementsCollection.cs
  16. 13
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
  17. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs
  18. 14
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs
  19. 66
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs
  20. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
  21. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs
  22. 19
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
  23. 22
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
  24. 7
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs
  25. 7
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs
  26. 3
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs
  27. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs
  28. 22
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs
  29. 52
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs
  30. 38
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs
  31. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs

4
src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml

@ -29,7 +29,9 @@
<Button>CB</Button> <Button>CB</Button>
</Canvas> </Canvas>
<Button>Button 1</Button> <Button>Button 1</Button>
<Button>Button 2</Button> <Canvas Height="50">
<Button>Button 2</Button>
</Canvas>
<TabControl Width="300" MinHeight="100"> <TabControl Width="300" MinHeight="100">
<TabItem Header="Page 1"><StackPanel><Button>a</Button></StackPanel> </TabItem> <TabItem Header="Page 1"><StackPanel><Button>a</Button></StackPanel> </TabItem>
<TabItem Header="Page 2"><Button>button on page 2</Button></TabItem> <TabItem Header="Page 2"><Button>button on page 2</Button></TabItem>

29
src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs

@ -1,12 +1,10 @@
using System; using System;
using System.Diagnostics; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Xml; using System.Xml;
using ICSharpCode.WpfDesign; using ICSharpCode.WpfDesign;
using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.Designer;
using ICSharpCode.WpfDesign.PropertyEditor; using ICSharpCode.WpfDesign.PropertyEditor;
@ -63,9 +61,30 @@ namespace StandaloneDesigner
} }
} }
ICollection<DesignItem> oldItems = new DesignItem[0];
void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e) void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e)
{ {
//propertyEditor.EditedObject = DesignItemDataSource.GetDataSourceForDesignItems(designSurface.DesignContext.Services.Selection.SelectedItems); ISelectionService selectionService = designSurface.DesignContext.Services.Selection;
ICollection<DesignItem> items = selectionService.SelectedItems;
if (!IsCollectionWithSameElements(items, oldItems)) {
propertyEditor.EditedObject = DesignItemDataSource.GetDataSourceForDesignItems(items);
oldItems = items;
}
}
static bool IsCollectionWithSameElements(ICollection<DesignItem> a, ICollection<DesignItem> b)
{
return ContainsAll(a, b) && ContainsAll(b, a);
}
static bool ContainsAll(ICollection<DesignItem> a, ICollection<DesignItem> b)
{
foreach (DesignItem item in a) {
if (!b.Contains(item))
return false;
}
return true;
} }
} }
} }

9
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Designer.Services;
namespace ICSharpCode.WpfDesign.Designer.Controls namespace ICSharpCode.WpfDesign.Designer.Controls
{ {
@ -33,6 +34,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
{ {
this.GrayOutBrush = new SolidColorBrush(SystemColors.GrayTextColor); this.GrayOutBrush = new SolidColorBrush(SystemColors.GrayTextColor);
this.GrayOutBrush.Opacity = MaxOpacity; this.GrayOutBrush.Opacity = MaxOpacity;
this.IsHitTestVisible = false;
} }
public Brush GrayOutBrush { public Brush GrayOutBrush {
@ -53,10 +55,13 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
drawingContext.DrawGeometry(grayOutBrush, null, combinedGeometry); drawingContext.DrawGeometry(grayOutBrush, null, combinedGeometry);
} }
internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, IDesignPanel designPanel, UIElement activeContainer) internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, ServiceContainer services, UIElement activeContainer)
{ {
Debug.Assert(services != null);
Debug.Assert(activeContainer != null); Debug.Assert(activeContainer != null);
if (designPanel != null && grayOut == null) { IDesignPanel designPanel = services.GetService<IDesignPanel>();
OptionService optionService = services.GetService<OptionService>();
if (designPanel != null && grayOut == null && optionService != null && optionService.GrayOutDesignSurfaceExceptParentContainerWhenDragging) {
grayOut = new GrayOutDesignerExceptActiveArea(); grayOut = new GrayOutDesignerExceptActiveArea();
grayOut.designPanel = designPanel; grayOut.designPanel = designPanel;
grayOut.adornerPanel = new AdornerPanel(); grayOut.adornerPanel = new AdornerPanel();

39
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs

@ -43,6 +43,17 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.AllowsTransparencyProperty, value); } set { SetValue(Window.AllowsTransparencyProperty, value); }
} }
/// <summary>
/// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary>
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), TypeConverter(typeof(DialogResultConverter))]
public bool? DialogResult {
get {
return null;
}
set { }
}
/// <summary> /// <summary>
/// Specifies the icon to use. /// Specifies the icon to use.
/// </summary> /// </summary>
@ -60,6 +71,16 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.LeftProperty, value); } set { SetValue(Window.LeftProperty, value); }
} }
Window owner;
/// <summary>
/// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary>
public Window Owner {
get { return owner; }
set { owner = value; }
}
/// <summary> /// <summary>
/// Gets or sets the resize mode. /// Gets or sets the resize mode.
/// </summary> /// </summary>
@ -109,6 +130,24 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.TopmostProperty, value); } set { SetValue(Window.TopmostProperty, value); }
} }
WindowStartupLocation windowStartupLocation;
/// <summary>
/// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary>
public WindowStartupLocation WindowStartupLocation {
get { return windowStartupLocation; }
set { windowStartupLocation = value; }
}
/// <summary>
/// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary>
public WindowState WindowState {
get { return (WindowState) GetValue(Window.WindowStateProperty); }
set { SetValue(Window.WindowStateProperty, value); }
}
/// <summary> /// <summary>
/// This property has no effect. (for compatibility with <see cref="Window"/> only). /// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary> /// </summary>

107
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs

@ -38,17 +38,10 @@ namespace ICSharpCode.WpfDesign.Designer
} }
} }
// Like VisualTreeHelper.HitTest(Visual,Point); but allows using a filter callback. static void RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback)
static PointHitTestResult RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback)
{ {
HitTestResult result = null; VisualTreeHelper.HitTest(reference, filterCallback, resultCallback,
VisualTreeHelper.HitTest(reference, filterCallback,
delegate (HitTestResult resultParameter) {
result = resultParameter;
return HitTestResultBehavior.Stop;
},
new PointHitTestParameters(point)); new PointHitTestParameters(point));
return result as PointHitTestResult;
} }
static HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialHitTestTarget) static HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialHitTestTarget)
@ -62,65 +55,81 @@ namespace ICSharpCode.WpfDesign.Designer
return HitTestFilterBehavior.Continue; return HitTestFilterBehavior.Continue;
} }
DesignPanelHitTestResult _lastHitTestResult;
/// <summary> /// <summary>
/// Performs a custom hit testing lookup for the specified mouse event args. /// Performs a custom hit testing lookup for the specified mouse event args.
/// </summary> /// </summary>
public DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface) public DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface)
{ {
_lastHitTestResult = CustomHitTestInternal(e.GetPosition(this), testAdorners, testDesignSurface); DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit;
return _lastHitTestResult; HitTest(e, testAdorners, testDesignSurface,
delegate(DesignPanelHitTestResult r) {
result = r;
return false;
});
return result;
} }
DesignPanelHitTestResult CustomHitTestInternal(Point mousePosition, bool testAdorners, bool testDesignSurface) /// <summary>
/// Performs a hit test on the design surface, raising <paramref name="callback"/> for each match.
/// Hit testing continues while the callback returns true.
/// </summary>
public void HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback)
{ {
Point mousePosition = e.GetPosition(this);
if (mousePosition.X < 0 || mousePosition.Y < 0 || mousePosition.X > this.RenderSize.Width || mousePosition.Y > this.RenderSize.Height) { if (mousePosition.X < 0 || mousePosition.Y < 0 || mousePosition.X > this.RenderSize.Width || mousePosition.Y > this.RenderSize.Height) {
return DesignPanelHitTestResult.NoHit; return;
} }
// First try hit-testing on the adorner layer. // First try hit-testing on the adorner layer.
PointHitTestResult result; bool continueHitTest = true;
DesignPanelHitTestResult customResult;
if (testAdorners) { if (testAdorners) {
result = RunHitTest(_adornerLayer, mousePosition, FilterHitTestInvisibleElements); RunHitTest(
if (result != null && result.VisualHit != null) { _adornerLayer, mousePosition, FilterHitTestInvisibleElements,
if (result.VisualHit == _lastHitTestResult.VisualHit) delegate(HitTestResult result) {
return _lastHitTestResult; if (result != null && result.VisualHit != null && result.VisualHit is Visual) {
customResult = new DesignPanelHitTestResult(result.VisualHit); DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit);
DependencyObject obj = result.VisualHit; DependencyObject obj = result.VisualHit;
while (obj != null && obj != _adornerLayer) { while (obj != null && obj != _adornerLayer) {
AdornerPanel adorner = obj as AdornerPanel; AdornerPanel adorner = obj as AdornerPanel;
if (adorner != null) { if (adorner != null) {
customResult.AdornerHit = adorner; customResult.AdornerHit = adorner;
}
obj = VisualTreeHelper.GetParent(obj);
}
continueHitTest = callback(customResult);
return continueHitTest ? HitTestResultBehavior.Continue : HitTestResultBehavior.Stop;
} else {
return HitTestResultBehavior.Continue;
} }
obj = VisualTreeHelper.GetParent(obj); });
}
return customResult;
}
} }
if (testDesignSurface) { if (continueHitTest && testDesignSurface) {
result = RunHitTest(this.Child, mousePosition, delegate { return HitTestFilterBehavior.Continue; }); RunHitTest(
if (result != null && result.VisualHit != null) { this.Child, mousePosition, delegate { return HitTestFilterBehavior.Continue; },
customResult = new DesignPanelHitTestResult(result.VisualHit); delegate(HitTestResult result) {
if (result != null && result.VisualHit != null && result.VisualHit is Visual) {
ViewService viewService = _context.Services.View; DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit);
DependencyObject obj = result.VisualHit;
while (obj != null) { ViewService viewService = _context.Services.View;
if ((customResult.ModelHit = viewService.GetModel(obj)) != null) DependencyObject obj = result.VisualHit;
break; while (obj != null) {
obj = VisualTreeHelper.GetParent(obj); if ((customResult.ModelHit = viewService.GetModel(obj)) != null)
} break;
if (customResult.ModelHit == null) obj = VisualTreeHelper.GetParent(obj);
{ }
customResult.ModelHit = _context.RootItem; if (customResult.ModelHit == null) {
customResult.ModelHit = _context.RootItem;
}
continueHitTest = callback(customResult);
return continueHitTest ? HitTestResultBehavior.Continue : HitTestResultBehavior.Stop;
} else {
return HitTestResultBehavior.Continue;
}
} }
return customResult; );
}
} }
return DesignPanelHitTestResult.NoHit;
} }
#endregion #endregion

48
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs

@ -37,18 +37,15 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
} }
/// <inherits/> /// <inherits/>
public void StartPlacement(PlacementOperation operation, out bool supportsRemoveFromContainer) public void StartPlacement(PlacementOperation operation)
{ {
supportsRemoveFromContainer = false;
//DesignItemProperty margin = operation.PlacedItem.Properties[FrameworkElement.MarginProperty];
UIElement child = (UIElement)operation.PlacedItem.Component; UIElement child = (UIElement)operation.PlacedItem.Component;
operation.Left = GetLeft(child); operation.Left = GetLeft(child);
operation.Top = GetTop(child); operation.Top = GetTop(child);
operation.Right = operation.Left + GetWidth(child); operation.Right = operation.Left + GetWidth(child);
operation.Bottom = operation.Top + GetHeight(child); operation.Bottom = operation.Top + GetHeight(child);
GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services.GetService<IDesignPanel>(), this.ExtendedItem.View); BeginPlacement();
} }
static double GetLeft(UIElement element) static double GetLeft(UIElement element)
@ -108,8 +105,49 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
/// <inherits/> /// <inherits/>
public void FinishPlacement(PlacementOperation operation) public void FinishPlacement(PlacementOperation operation)
{
EndPlacement();
}
void BeginPlacement()
{
GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services, this.ExtendedItem.View);
}
void EndPlacement()
{ {
GrayOutDesignerExceptActiveArea.Stop(ref grayOut); GrayOutDesignerExceptActiveArea.Stop(ref grayOut);
} }
/// <inherits/>
public bool CanLeaveContainer(PlacementOperation operation)
{
return true;
}
/// <inherits/>
public void LeaveContainer(PlacementOperation operation)
{
EndPlacement();
this.ExtendedItem.Properties["Children"].CollectionElements.Remove(operation.PlacedItem);
operation.PlacedItem.Properties.GetAttachedProperty(Canvas.LeftProperty).Reset();
operation.PlacedItem.Properties.GetAttachedProperty(Canvas.TopProperty).Reset();
}
/// <inherits/>
public bool CanEnterContainer(PlacementOperation operation)
{
return true;
}
/// <inherits/>
public void EnterContainer(PlacementOperation operation)
{
this.ExtendedItem.Properties["Children"].CollectionElements.Add(operation.PlacedItem);
UpdatePlacement(operation);
BeginPlacement();
}
} }
} }

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs

@ -64,7 +64,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
designPanel.Adorners.Add(adornerPanel); designPanel.Adorners.Add(adornerPanel);
GrayOutDesignerExceptActiveArea.Start(ref grayOut, designPanel, container.View); GrayOutDesignerExceptActiveArea.Start(ref grayOut, services, container.View);
} }
protected override void OnMouseMove(object sender, MouseEventArgs e) protected override void OnMouseMove(object sender, MouseEventArgs e)

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs

@ -96,7 +96,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
operation.Bottom = operation.Top; operation.Bottom = operation.Top;
break; break;
} }
operation.UpdatePlacement(); operation.CurrentContainerBehavior.UpdatePlacement(operation);
}; };
} }

105
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/WindowResizeBehavior.cs

@ -0,0 +1,105 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using ICSharpCode.WpfDesign.Extensions;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
/// <summary>
/// Supports resizing a Window.
/// </summary>
[ExtensionFor(typeof(Window))]
public class WindowResizeBehavior : BehaviorExtension, IRootPlacementBehavior
{
/// <inherits/>
protected override void OnInitialized()
{
base.OnInitialized();
this.ExtendedItem.AddBehavior(typeof(IRootPlacementBehavior), this);
}
/// <inherits/>
public bool CanPlace(DesignItem child, PlacementType type, PlacementAlignment position)
{
return type == PlacementType.Resize &&
(position == PlacementAlignments.Right
|| position == PlacementAlignments.BottomRight
|| position == PlacementAlignments.Bottom);
}
/// <inherits/>
public void StartPlacement(PlacementOperation operation)
{
UIElement element = (UIElement)operation.PlacedItem.Component;
operation.Left = 0;
operation.Top = 0;
operation.Right = GetWidth(element);
operation.Bottom = GetHeight(element);
}
static double GetWidth(UIElement element)
{
double v = (double)element.GetValue(FrameworkElement.WidthProperty);
if (double.IsNaN(v))
return element.RenderSize.Width;
else
return v;
}
static double GetHeight(UIElement element)
{
double v = (double)element.GetValue(FrameworkElement.HeightProperty);
if (double.IsNaN(v))
return element.RenderSize.Height;
else
return v;
}
/// <inherits/>
public void UpdatePlacement(PlacementOperation operation)
{
UIElement element = (UIElement)operation.PlacedItem.Component;
if (operation.Right != GetWidth(element)) {
operation.PlacedItem.Properties[FrameworkElement.WidthProperty].SetValue(operation.Right);
}
if (operation.Bottom != GetHeight(element)) {
operation.PlacedItem.Properties[FrameworkElement.HeightProperty].SetValue(operation.Bottom);
}
}
/// <inherits/>
public void FinishPlacement(PlacementOperation operation)
{
}
/// <inherits/>
public bool CanLeaveContainer(PlacementOperation operation)
{
return false;
}
/// <inherits/>
public void LeaveContainer(PlacementOperation operation)
{
throw new NotSupportedException();
}
/// <inherits/>
public bool CanEnterContainer(PlacementOperation operation)
{
return false;
}
/// <inherits/>
public void EnterContainer(PlacementOperation operation)
{
throw new NotSupportedException();
}
}
}

51
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs

@ -51,15 +51,64 @@ namespace ICSharpCode.WpfDesign.Designer.Services
{ {
base.OnMouseMove(sender, e); // call OnDragStarted if min. drag distace is reached base.OnMouseMove(sender, e); // call OnDragStarted if min. drag distace is reached
if (operation != null) { if (operation != null) {
UIElement currentContainer = operation.CurrentContainer.View;
Point p = e.GetPosition(currentContainer);
if (p.X < 0 || p.Y < 0 || p.X > currentContainer.RenderSize.Width || p.Y > currentContainer.RenderSize.Height) {
// outside the bounds of the current container
if (operation.CurrentContainerBehavior.CanLeaveContainer(operation)) {
if (ChangeContainerIfPossible(e)) {
return;
}
}
}
Vector v = e.GetPosition(positionRelativeTo) - startPoint; Vector v = e.GetPosition(positionRelativeTo) - startPoint;
operation.Left = startLeft + v.X; operation.Left = startLeft + v.X;
operation.Right = startRight + v.X; operation.Right = startRight + v.X;
operation.Top = startTop + v.Y; operation.Top = startTop + v.Y;
operation.Bottom = startBottom + v.Y; operation.Bottom = startBottom + v.Y;
operation.UpdatePlacement(); operation.CurrentContainerBehavior.UpdatePlacement(operation);
} }
} }
// Perform hit testing on the design panel and return the first model that is not selected
DesignPanelHitTestResult HitTestUnselectedModel(MouseEventArgs e)
{
DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit;
ISelectionService selection = services.Selection;
designPanel.HitTest(
e, false, true,
delegate(DesignPanelHitTestResult r) {
if (r.ModelHit == null)
return true; // continue hit testing
if (selection.IsComponentSelected(r.ModelHit))
return true; // continue hit testing
result = r;
return false; // finish hit testing
});
return result;
}
bool ChangeContainerIfPossible(MouseEventArgs e)
{
DesignPanelHitTestResult result = HitTestUnselectedModel(e);
if (result.ModelHit == null) return false;
// check that we don't move an item into itself:
DesignItem tmp = result.ModelHit;
while (tmp != null) {
if (tmp == clickedOn) return false;
tmp = tmp.Parent;
}
IPlacementBehavior b = result.ModelHit.GetBehavior<IPlacementBehavior>();
if (b != null && b.CanEnterContainer(operation)) {
operation.ChangeContainer(result.ModelHit);
return true;
}
return false;
}
protected override void OnMouseUp(object sender, MouseButtonEventArgs e) protected override void OnMouseUp(object sender, MouseButtonEventArgs e)
{ {
if (operation != null) { if (operation != null) {

22
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/OptionService.cs

@ -0,0 +1,22 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.WpfDesign.Designer.Services
{
/// <summary>
/// Contains a set of options regarding the default designer components.
/// </summary>
public sealed class OptionService
{
/// <summary>
/// Gets/Sets whether the design surface should be grayed out while dragging/selection.
/// </summary>
public bool GrayOutDesignSurfaceExceptParentContainerWhenDragging = true;
}
}

3
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -78,16 +78,19 @@
<Compile Include="Extensions\TabItemClickableExtension.cs" /> <Compile Include="Extensions\TabItemClickableExtension.cs" />
<Compile Include="Extensions\TopLeftContainerDragHandle.cs" /> <Compile Include="Extensions\TopLeftContainerDragHandle.cs" />
<Compile Include="Extensions\ResizeThumbExtension.cs" /> <Compile Include="Extensions\ResizeThumbExtension.cs" />
<Compile Include="Extensions\WindowResizeBehavior.cs" />
<Compile Include="Func.cs" /> <Compile Include="Func.cs" />
<Compile Include="ServiceRequiredException.cs" /> <Compile Include="ServiceRequiredException.cs" />
<Compile Include="Services\ClickOrDragMouseGesture.cs" /> <Compile Include="Services\ClickOrDragMouseGesture.cs" />
<Compile Include="Services\DragMoveMouseGesture.cs" /> <Compile Include="Services\DragMoveMouseGesture.cs" />
<Compile Include="Services\ErrorService.cs" /> <Compile Include="Services\ErrorService.cs" />
<Compile Include="Services\OptionService.cs" />
<Compile Include="Services\SelectionService.cs" /> <Compile Include="Services\SelectionService.cs" />
<Compile Include="Services\ToolService.cs" /> <Compile Include="Services\ToolService.cs" />
<Compile Include="Services\UndoService.cs" /> <Compile Include="Services\UndoService.cs" />
<Compile Include="Services\ViewService.cs" /> <Compile Include="Services\ViewService.cs" />
<Compile Include="DesignSurface.cs" /> <Compile Include="DesignSurface.cs" />
<Compile Include="Xaml\XamlModelCollectionElementsCollection.cs" />
<Compile Include="Xaml\XamlComponentService.cs" /> <Compile Include="Xaml\XamlComponentService.cs" />
<Compile Include="Xaml\XamlDesignContext.cs" /> <Compile Include="Xaml\XamlDesignContext.cs" />
<Compile Include="Xaml\XamlDesignItem.cs" /> <Compile Include="Xaml\XamlDesignItem.cs" />

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

@ -41,6 +41,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
this.Services.AddService(typeof(UndoService), new UndoService()); this.Services.AddService(typeof(UndoService), new UndoService());
this.Services.AddService(typeof(IErrorService), new DefaultErrorService()); this.Services.AddService(typeof(IErrorService), new DefaultErrorService());
this.Services.AddService(typeof(ViewService), new DefaultViewService(this)); this.Services.AddService(typeof(ViewService), new DefaultViewService(this));
this.Services.AddService(typeof(OptionService), new OptionService());
_componentService = new XamlComponentService(this); _componentService = new XamlComponentService(this);
this.Services.AddService(typeof(IComponentService), _componentService); this.Services.AddService(typeof(IComponentService), _componentService);

8
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs

@ -46,6 +46,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
} }
} }
public override Type ComponentType {
get { return _xamlObject.ElementType; }
}
public override string Name { public override string Name {
get { return (string)this.Properties["Name"].ValueOnInstance; } get { return (string)this.Properties["Name"].ValueOnInstance; }
set { this.Properties["Name"].SetValue(value); } set { this.Properties["Name"].SetValue(value); }
@ -61,13 +65,13 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override event EventHandler NameChanged { public override event EventHandler NameChanged {
add { add {
#if EventHandlerDebugging #if EventHandlerDebugging
Debug.WriteLine("Add event handler to " + this.Component.GetType().Name + " (handler count=" + (++totalEventHandlerCount) + ")"); Debug.WriteLine("Add event handler to " + this.ComponentType.Name + " (handler count=" + (++totalEventHandlerCount) + ")");
#endif #endif
this.Properties["Name"].ValueChanged += value; this.Properties["Name"].ValueChanged += value;
} }
remove { remove {
#if EventHandlerDebugging #if EventHandlerDebugging
Debug.WriteLine("Remove event handler from " + this.Component.GetType().Name + " (handler count=" + (--totalEventHandlerCount) + ")"); Debug.WriteLine("Remove event handler from " + this.ComponentType.Name + " (handler count=" + (--totalEventHandlerCount) + ")");
#endif #endif
this.Properties["Name"].ValueChanged -= value; this.Properties["Name"].ValueChanged -= value;
} }

77
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelCollectionElementsCollection.cs

@ -0,0 +1,77 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ICSharpCode.WpfDesign.XamlDom;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
sealed class XamlModelCollectionElementsCollection : Collection<DesignItem>
{
readonly XamlModelProperty modelProperty;
readonly XamlProperty property;
public XamlModelCollectionElementsCollection(XamlModelProperty modelProperty, XamlProperty property)
{
this.modelProperty = modelProperty;
this.property = property;
XamlDesignContext context = (XamlDesignContext)modelProperty.DesignItem.Context;
foreach (XamlPropertyValue val in property.CollectionElements) {
//context._componentService.GetDesignItem(val);
if (val is XamlObject) {
base.InsertItem(this.Count, context._componentService.GetDesignItem( ((XamlObject)val).Instance ));
}
}
}
protected override void ClearItems()
{
base.ClearItems();
property.CollectionElements.Clear();
}
XamlDesignItem CheckItem(DesignItem item)
{
if (item == null)
throw new ArgumentNullException("item");
if (item.Context != modelProperty.DesignItem.Context)
throw new ArgumentException("The item must belong to the same context as this collection", "item");
XamlDesignItem xitem = item as XamlDesignItem;
Debug.Assert(xitem != null);
return xitem;
}
protected override void InsertItem(int index, DesignItem item)
{
XamlDesignItem xitem = CheckItem(item);
property.CollectionElements.Insert(index, xitem.XamlObject);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
XamlDesignItem item = (XamlDesignItem)this[index];
property.CollectionElements.RemoveAt(index);
base.RemoveItem(index);
}
protected override void SetItem(int index, DesignItem item)
{
XamlDesignItem xitem = CheckItem(item);
property.CollectionElements[index] = xitem.XamlObject;
base.SetItem(index, item);
}
}
}

13
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs

@ -19,6 +19,11 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
{ {
readonly XamlDesignItem _designItem; readonly XamlDesignItem _designItem;
readonly XamlProperty _property; readonly XamlProperty _property;
readonly XamlModelCollectionElementsCollection _collectionElements;
internal XamlDesignItem DesignItem {
get { return _designItem; }
}
public XamlModelProperty(XamlDesignItem designItem, XamlProperty property) public XamlModelProperty(XamlDesignItem designItem, XamlProperty property)
{ {
@ -27,6 +32,9 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
this._designItem = designItem; this._designItem = designItem;
this._property = property; this._property = property;
if (property.IsCollection) {
_collectionElements = new XamlModelCollectionElementsCollection(this, property);
}
} }
public override bool Equals(object obj) public override bool Equals(object obj)
@ -70,7 +78,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override System.Collections.Generic.IList<DesignItem> CollectionElements { public override System.Collections.Generic.IList<DesignItem> CollectionElements {
get { get {
throw new NotImplementedException(); if (!IsCollection)
throw new DesignerException("Cannot access CollectionElements for non-collection properties.");
else
return _collectionElements;
} }
} }

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs

@ -78,7 +78,7 @@ namespace ICSharpCode.WpfDesign.Designer.Tests
static string ItemIdentity(DesignItem item) static string ItemIdentity(DesignItem item)
{ {
return item.Component.GetType().Name + " (" + item.GetHashCode() + ")"; return item.ComponentType.Name + " (" + item.GetHashCode() + ")";
} }
protected void AssertLog(string expectedLog) protected void AssertLog(string expectedLog)

14
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs

@ -10,6 +10,8 @@ using System.Text;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
using System.Diagnostics; using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.WpfDesign.Designer.Xaml; using ICSharpCode.WpfDesign.Designer.Xaml;
using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Services;
@ -75,5 +77,17 @@ namespace ICSharpCode.WpfDesign.Designer.Tests
AssertCanvasDesignerOutput(@"<Button Width=""100"" Height=""200"" />", button.Context); AssertCanvasDesignerOutput(@"<Button Width=""100"" Height=""200"" />", button.Context);
AssertLog(""); AssertLog("");
} }
[Test]
public void AddTextBoxToStackPanel()
{
DesignItem button = CreateCanvasContext("<Button/>");
DesignItem canvas = button.Parent;
DesignItem textBox = canvas.Services.Component.RegisterComponentForDesigner(new TextBox());
canvas.Properties["Children"].CollectionElements.Add(textBox);
AssertCanvasDesignerOutput("<Button />\n<TextBox />", button.Context);
AssertLog("");
}
} }
} }

66
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs

@ -0,0 +1,66 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
namespace ICSharpCode.WpfDesign.XamlDom
{
partial class XamlProperty
{
/// <summary>
/// The collection used by XamlProperty.CollectionElements
/// </summary>
sealed class CollectionElementsCollection : Collection<XamlPropertyValue>
{
XamlProperty property;
internal CollectionElementsCollection(XamlProperty property)
{
this.property = property;
}
internal void AddByParser(XamlPropertyValue value)
{
base.InsertItem(this.Count, value);
}
protected override void ClearItems()
{
while (Count > 0) {
RemoveAt(Count - 1);
}
}
protected override void RemoveItem(int index)
{
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));
}
this[index].RemoveNodeFromParent();
this[index].ParentProperty = null;
base.RemoveItem(index);
}
protected override void InsertItem(int index, XamlPropertyValue item)
{
XamlPropertyInfo info = property.propertyInfo;
object collection = info.GetValue(property.ParentObject.Instance);
info.AddValue(collection, item);
item.AddNodeTo(property);
item.ParentProperty = property;
base.InsertItem(index, item);
}
}
}
}

1
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj

@ -58,6 +58,7 @@
<Link>GlobalAssemblyInfo.cs</Link> <Link>GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyInfo.cs" />
<Compile Include="CollectionElementsCollection.cs" />
<Compile Include="XamlConstants.cs" /> <Compile Include="XamlConstants.cs" />
<Compile Include="XamlDocument.cs" /> <Compile Include="XamlDocument.cs" />
<Compile Include="XamlLoadException.cs" /> <Compile Include="XamlLoadException.cs" />

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs

@ -29,6 +29,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
return ((MarkupExtension)markupObject.Instance).ProvideValue(doc.ServiceProvider); return ((MarkupExtension)markupObject.Instance).ProvideValue(doc.ServiceProvider);
} }
internal override void OnParentPropertyChanged()
{
base.OnParentPropertyChanged();
markupObject.ParentProperty = this.ParentProperty;
}
internal override void RemoveNodeFromParent() internal override void RemoveNodeFromParent()
{ {
markupObject.RemoveNodeFromParent(); markupObject.RemoveNodeFromParent();

19
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -17,13 +17,13 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// <summary> /// <summary>
/// Describes a property on a <see cref="XamlObject"/>. /// Describes a property on a <see cref="XamlObject"/>.
/// </summary> /// </summary>
public sealed class XamlProperty public sealed partial class XamlProperty
{ {
XamlObject parentObject; XamlObject parentObject;
XamlPropertyInfo propertyInfo; XamlPropertyInfo propertyInfo;
XamlPropertyValue propertyValue; XamlPropertyValue propertyValue;
List<XamlPropertyValue> collectionElements; CollectionElementsCollection collectionElements;
bool isCollection; bool isCollection;
static readonly IList<XamlPropertyValue> emptyCollectionElementsArray = new XamlPropertyValue[0]; static readonly IList<XamlPropertyValue> emptyCollectionElementsArray = new XamlPropertyValue[0];
@ -40,7 +40,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
} else { } else {
if (propertyInfo.IsCollection) { if (propertyInfo.IsCollection) {
isCollection = true; isCollection = true;
collectionElements = new List<XamlPropertyValue>(); collectionElements = new CollectionElementsCollection(this);
} }
} }
} }
@ -159,7 +159,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// Gets the collection elements of the property. Is empty if the property is not a collection. /// Gets the collection elements of the property. Is empty if the property is not a collection.
/// </summary> /// </summary>
public IList<XamlPropertyValue> CollectionElements { public IList<XamlPropertyValue> CollectionElements {
get { return collectionElements != null ? collectionElements.AsReadOnly() : emptyCollectionElementsArray; } get { return collectionElements ?? emptyCollectionElementsArray; }
} }
/// <summary> /// <summary>
@ -217,7 +217,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// </summary> /// </summary>
internal void ParserAddCollectionElement(XamlPropertyValue val) internal void ParserAddCollectionElement(XamlPropertyValue val)
{ {
collectionElements.Add(val); collectionElements.AddByParser(val);
val.ParentProperty = this; val.ParentProperty = this;
} }
@ -270,7 +270,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// </summary> /// </summary>
public XamlProperty ParentProperty { public XamlProperty ParentProperty {
get { return _parentProperty; } get { return _parentProperty; }
internal set { _parentProperty = value; } internal set {
_parentProperty = value;
OnParentPropertyChanged();
}
}
internal virtual void OnParentPropertyChanged()
{
} }
internal abstract void RemoveNodeFromParent(); internal abstract void RemoveNodeFromParent();

22
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs

@ -203,5 +203,27 @@ namespace ICSharpCode.WpfDesign.XamlDom
CultureInfo.InvariantCulture); CultureInfo.InvariantCulture);
} }
} }
static readonly Type[] RemoveAtParameters = { typeof(int) };
public static bool RemoveItemAt(Type collectionType, object collectionInstance, int index)
{
MethodInfo m = collectionType.GetMethod("RemoveAt", RemoveAtParameters);
if (m != null) {
m.Invoke(collectionInstance, new object[] { index });
return true;
} else {
return false;
}
}
public static void RemoveItem(Type collectionType, object collectionInstance, object item)
{
collectionType.InvokeMember(
"Remove", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
null, collectionInstance,
new object[] { item },
CultureInfo.InvariantCulture);
}
} }
} }

7
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs

@ -34,6 +34,11 @@ namespace ICSharpCode.WpfDesign.XamlDom.Tests
public class ExampleDependencyObject : DependencyObject public class ExampleDependencyObject : DependencyObject
{ {
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
// TODO: add this test, check for correct setting of NameScope
//TestHelperLog.Log("ExampleDependencyObject.OnPropertyChanged " + e.Property.Name);
}
} }
} }

7
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs

@ -26,6 +26,13 @@ namespace ICSharpCode.WpfDesign
/// </summary> /// </summary>
public abstract object Component { get; } public abstract object Component { get; }
/// <summary>
/// Gets the component type of this design site.
/// This value may be different from Component.GetType() if a CustomInstanceFactory created
/// an object using a different type.
/// </summary>
public abstract Type ComponentType { get; }
/// <summary> /// <summary>
/// Gets the view used for the component. /// Gets the view used for the component.
/// </summary> /// </summary>

3
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs

@ -6,13 +6,14 @@
// </file> // </file>
using System; using System;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Adorners;
namespace ICSharpCode.WpfDesign namespace ICSharpCode.WpfDesign
{ {
/// <summary> /// <summary>
/// Describes the result of a <see cref="IDesignPanel.HitTest"/> call. /// Describes the result of a <see cref="IDesignPanel.HitTest(MouseEventArgs, bool, bool)"/> call.
/// </summary> /// </summary>
public struct DesignPanelHitTestResult : IEquatable<DesignPanelHitTestResult> public struct DesignPanelHitTestResult : IEquatable<DesignPanelHitTestResult>
{ {

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.WpfDesign.Extensions
if (extendedItem.Component == null) if (extendedItem.Component == null)
return emptyExtensionEntryArray; return emptyExtensionEntryArray;
else else
return GetExtensionEntries(extendedItem.Component.GetType()); return GetExtensionEntries(extendedItem.ComponentType);
} }
ExtensionServer[] GetExtensionServersForItem(DesignItem item) ExtensionServer[] GetExtensionServersForItem(DesignItem item)

22
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs

@ -27,13 +27,33 @@ namespace ICSharpCode.WpfDesign
/// <summary> /// <summary>
/// Starts placement mode of the child element specified in the placement operation. /// Starts placement mode of the child element specified in the placement operation.
/// </summary> /// </summary>
void StartPlacement(PlacementOperation operation, out bool supportsRemoveFromContainer); void StartPlacement(PlacementOperation operation);
/// <summary> /// <summary>
/// Updates the placement of the element specified in the placement operation. /// Updates the placement of the element specified in the placement operation.
/// </summary> /// </summary>
void UpdatePlacement(PlacementOperation operation); void UpdatePlacement(PlacementOperation operation);
/// <summary>
/// Gets if leaving this container is allowed for the specified operation.
/// </summary>
bool CanLeaveContainer(PlacementOperation operation);
/// <summary>
/// Remove the placed child from this container.
/// </summary>
void LeaveContainer(PlacementOperation operation);
/// <summary>
/// Gets if entering this container is allowed for the specified operation.
/// </summary>
bool CanEnterContainer(PlacementOperation operation);
/// <summary>
/// Let the placed child enter this container.
/// </summary>
void EnterContainer(PlacementOperation operation);
/// <summary> /// <summary>
/// Finishes placement of a child element. This method is called both for aborted /// Finishes placement of a child element. This method is called both for aborted
/// and committed placement operations. /// and committed placement operations.

52
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs

@ -6,6 +6,7 @@
// </file> // </file>
using System; using System;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@ -25,11 +26,8 @@ namespace ICSharpCode.WpfDesign
readonly IPlacementBehavior oldContainerBehavior; readonly IPlacementBehavior oldContainerBehavior;
DesignItem currentContainer; DesignItem currentContainer;
IPlacementBehavior currentContainerBehavior; IPlacementBehavior currentContainerBehavior;
bool supportsRemoveFromContainer;
bool isAborted, isCommitted; bool isAborted, isCommitted;
//DesignItem newContainer;
#region Properties #region Properties
/// <summary> /// <summary>
/// The item being placed. /// The item being placed.
@ -45,13 +43,6 @@ namespace ICSharpCode.WpfDesign
get { return type; } get { return type; }
} }
/// <summary>
/// Gets if removing the placed item from the container is supported.
/// </summary>
public bool SupportsRemoveFromContainer {
get { return supportsRemoveFromContainer; }
}
/// <summary> /// <summary>
/// Gets if the placement operation was aborted. /// Gets if the placement operation was aborted.
/// </summary> /// </summary>
@ -72,11 +63,46 @@ namespace ICSharpCode.WpfDesign
/// </summary> /// </summary>
public double Left, Right, Top, Bottom; public double Left, Right, Top, Bottom;
/// <summary>
/// Gets the current container for the placement operation.
/// </summary>
public DesignItem CurrentContainer {
get { return currentContainer; }
}
/// <summary>
/// Gets the placement behavior for the current container.
/// </summary>
public IPlacementBehavior CurrentContainerBehavior {
get { return currentContainerBehavior; }
}
#endregion #endregion
public void UpdatePlacement() /// <summary>
/// Make the placed item switch the container.
/// This method assumes that you already have checked if changing the container is possible.
/// </summary>
public void ChangeContainer(DesignItem newContainer)
{ {
currentContainerBehavior.UpdatePlacement(this); if (newContainer == null)
throw new ArgumentNullException("newContainer");
if (currentContainer == newContainer)
return;
try {
currentContainerBehavior.LeaveContainer(this);
currentContainer = newContainer;
currentContainerBehavior = newContainer.GetBehavior<IPlacementBehavior>();
Debug.Assert(currentContainerBehavior != null);
currentContainerBehavior.EnterContainer(this);
} catch (Exception ex) {
Debug.WriteLine(ex.ToString());
Abort();
throw;
}
} }
#region Start #region Start
@ -101,7 +127,7 @@ namespace ICSharpCode.WpfDesign
if (op.currentContainerBehavior == null) if (op.currentContainerBehavior == null)
throw new InvalidOperationException("Starting the operation is not supported"); throw new InvalidOperationException("Starting the operation is not supported");
op.Left = op.Top = op.Bottom = op.Right = double.NaN; op.Left = op.Top = op.Bottom = op.Right = double.NaN;
op.currentContainerBehavior.StartPlacement(op, out op.supportsRemoveFromContainer); op.currentContainerBehavior.StartPlacement(op);
if (double.IsNaN(op.Left) || double.IsNaN(op.Top) || double.IsNaN(op.Bottom) || double.IsNaN(op.Right)) if (double.IsNaN(op.Left) || double.IsNaN(op.Top) || double.IsNaN(op.Bottom) || double.IsNaN(op.Right))
throw new InvalidOperationException("IPlacementBehavior.StartPlacement must set Left,Top,Right+Bottom to non-NAN values"); throw new InvalidOperationException("IPlacementBehavior.StartPlacement must set Left,Top,Right+Bottom to non-NAN values");
} catch { } catch {

38
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs

@ -7,6 +7,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Collections.Generic; using System.Collections.Generic;
@ -21,6 +22,34 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
readonly DesignItem item; readonly DesignItem item;
readonly List<IPropertyEditorDataProperty> properties = new List<IPropertyEditorDataProperty>(); readonly List<IPropertyEditorDataProperty> properties = new List<IPropertyEditorDataProperty>();
#region Available properties
// cache properties available for a type - retrieving this list takes ~100ms on my machine, so
// we cannot do this for every selected component, but must reuse the list
static readonly Dictionary<Type, string[]> availableProperties = new Dictionary<Type, string[]>();
static string[] GetAvailableProperties(Type forType)
{
Debug.Assert(forType != null);
string[] result;
lock (availableProperties) {
if (availableProperties.TryGetValue(forType, out result))
return result;
}
List<string> names = new List<string>();
foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(forType)) {
if (!p.IsBrowsable) continue;
if (p.IsReadOnly) continue;
if (p.Name.Contains(".")) continue;
names.Add(p.Name);
}
result = names.ToArray();
lock (availableProperties) {
availableProperties[forType] = result;
}
return result;
}
#endregion
/// <summary> /// <summary>
/// Constructs a new DesignItemDataSource for the specified design item. /// Constructs a new DesignItemDataSource for the specified design item.
/// </summary> /// </summary>
@ -31,11 +60,8 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
this.item = item; this.item = item;
List<DesignItemProperty> designItemProperties = new List<DesignItemProperty>(); List<DesignItemProperty> designItemProperties = new List<DesignItemProperty>();
foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(item.Component)) { foreach (string name in GetAvailableProperties(item.ComponentType)) {
if (!p.IsBrowsable) continue; designItemProperties.Add(item.Properties[name]);
if (p.IsReadOnly) continue;
if (p.Name.Contains(".")) continue;
designItemProperties.Add(item.Properties[p.Name]);
} }
designItemProperties.AddRange(item.Properties); designItemProperties.AddRange(item.Properties);
@ -99,7 +125,7 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary> /// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
public string Type { public string Type {
get { get {
return item.Component.GetType().Name; return item.ComponentType.Name;
} }
} }

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs

@ -85,6 +85,12 @@ namespace ICSharpCode.WpfDesign
/// </summary> /// </summary>
DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface); DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface);
/// <summary>
/// Performs a hit test on the design surface, raising <paramref name="callback"/> for each match.
/// Hit testing continues while the callback returns true.
/// </summary>
void HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface, Predicate<DesignPanelHitTestResult> callback);
// The following members were missing in <see cref="IInputElement"/>, but // The following members were missing in <see cref="IInputElement"/>, but
// are supported on the DesignPanel: // are supported on the DesignPanel:

Loading…
Cancel
Save