diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
index 5a3c754aa9..31daad2eec 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
+++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
@@ -29,7 +29,9 @@
-
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
index d381a93df7..90939d7d27 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
@@ -1,12 +1,10 @@
using System;
-using System.Diagnostics;
+using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Markup;
using System.Xml;
+
using ICSharpCode.WpfDesign;
using ICSharpCode.WpfDesign.Designer;
using ICSharpCode.WpfDesign.PropertyEditor;
@@ -63,9 +61,30 @@ namespace StandaloneDesigner
}
}
+ ICollection oldItems = new DesignItem[0];
+
void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e)
{
- //propertyEditor.EditedObject = DesignItemDataSource.GetDataSourceForDesignItems(designSurface.DesignContext.Services.Selection.SelectedItems);
+ ISelectionService selectionService = designSurface.DesignContext.Services.Selection;
+ ICollection items = selectionService.SelectedItems;
+ if (!IsCollectionWithSameElements(items, oldItems)) {
+ propertyEditor.EditedObject = DesignItemDataSource.GetDataSourceForDesignItems(items);
+ oldItems = items;
+ }
+ }
+
+ static bool IsCollectionWithSameElements(ICollection a, ICollection b)
+ {
+ return ContainsAll(a, b) && ContainsAll(b, a);
+ }
+
+ static bool ContainsAll(ICollection a, ICollection b)
+ {
+ foreach (DesignItem item in a) {
+ if (!b.Contains(item))
+ return false;
+ }
+ return true;
}
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs
index b566802d5b..2a2b2ede70 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs
+++ b/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.Media.Animation;
using ICSharpCode.WpfDesign.Adorners;
+using ICSharpCode.WpfDesign.Designer.Services;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
@@ -33,6 +34,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
{
this.GrayOutBrush = new SolidColorBrush(SystemColors.GrayTextColor);
this.GrayOutBrush.Opacity = MaxOpacity;
+ this.IsHitTestVisible = false;
}
public Brush GrayOutBrush {
@@ -53,10 +55,13 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
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);
- if (designPanel != null && grayOut == null) {
+ IDesignPanel designPanel = services.GetService();
+ OptionService optionService = services.GetService();
+ if (designPanel != null && grayOut == null && optionService != null && optionService.GrayOutDesignSurfaceExceptParentContainerWhenDragging) {
grayOut = new GrayOutDesignerExceptActiveArea();
grayOut.designPanel = designPanel;
grayOut.adornerPanel = new AdornerPanel();
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs
index 690710080e..b4c07fdaf8 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs
@@ -43,6 +43,17 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.AllowsTransparencyProperty, value); }
}
+ ///
+ /// This property has no effect. (for compatibility with only).
+ ///
+ [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), TypeConverter(typeof(DialogResultConverter))]
+ public bool? DialogResult {
+ get {
+ return null;
+ }
+ set { }
+ }
+
///
/// Specifies the icon to use.
///
@@ -60,6 +71,16 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.LeftProperty, value); }
}
+ Window owner;
+
+ ///
+ /// This property has no effect. (for compatibility with only).
+ ///
+ public Window Owner {
+ get { return owner; }
+ set { owner = value; }
+ }
+
///
/// Gets or sets the resize mode.
///
@@ -109,6 +130,24 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(Window.TopmostProperty, value); }
}
+ WindowStartupLocation windowStartupLocation;
+
+ ///
+ /// This property has no effect. (for compatibility with only).
+ ///
+ public WindowStartupLocation WindowStartupLocation {
+ get { return windowStartupLocation; }
+ set { windowStartupLocation = value; }
+ }
+
+ ///
+ /// This property has no effect. (for compatibility with only).
+ ///
+ public WindowState WindowState {
+ get { return (WindowState) GetValue(Window.WindowStateProperty); }
+ set { SetValue(Window.WindowStateProperty, value); }
+ }
+
///
/// This property has no effect. (for compatibility with only).
///
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs
index 6351f3b888..f65cc0174d 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs
+++ b/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 PointHitTestResult RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback)
+ static void RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback)
{
- HitTestResult result = null;
- VisualTreeHelper.HitTest(reference, filterCallback,
- delegate (HitTestResult resultParameter) {
- result = resultParameter;
- return HitTestResultBehavior.Stop;
- },
+ VisualTreeHelper.HitTest(reference, filterCallback, resultCallback,
new PointHitTestParameters(point));
- return result as PointHitTestResult;
}
static HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialHitTestTarget)
@@ -62,65 +55,81 @@ namespace ICSharpCode.WpfDesign.Designer
return HitTestFilterBehavior.Continue;
}
- DesignPanelHitTestResult _lastHitTestResult;
-
///
/// Performs a custom hit testing lookup for the specified mouse event args.
///
public DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface)
{
- _lastHitTestResult = CustomHitTestInternal(e.GetPosition(this), testAdorners, testDesignSurface);
- return _lastHitTestResult;
+ DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit;
+ HitTest(e, testAdorners, testDesignSurface,
+ delegate(DesignPanelHitTestResult r) {
+ result = r;
+ return false;
+ });
+ return result;
}
- DesignPanelHitTestResult CustomHitTestInternal(Point mousePosition, bool testAdorners, bool testDesignSurface)
+ ///
+ /// Performs a hit test on the design surface, raising for each match.
+ /// Hit testing continues while the callback returns true.
+ ///
+ public void HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface, Predicate callback)
{
+ Point mousePosition = e.GetPosition(this);
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.
- PointHitTestResult result;
- DesignPanelHitTestResult customResult;
+ bool continueHitTest = true;
if (testAdorners) {
- result = RunHitTest(_adornerLayer, mousePosition, FilterHitTestInvisibleElements);
- if (result != null && result.VisualHit != null) {
- if (result.VisualHit == _lastHitTestResult.VisualHit)
- return _lastHitTestResult;
- customResult = new DesignPanelHitTestResult(result.VisualHit);
- DependencyObject obj = result.VisualHit;
- while (obj != null && obj != _adornerLayer) {
- AdornerPanel adorner = obj as AdornerPanel;
- if (adorner != null) {
- customResult.AdornerHit = adorner;
+ RunHitTest(
+ _adornerLayer, mousePosition, FilterHitTestInvisibleElements,
+ delegate(HitTestResult result) {
+ if (result != null && result.VisualHit != null && result.VisualHit is Visual) {
+ DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit);
+ DependencyObject obj = result.VisualHit;
+ while (obj != null && obj != _adornerLayer) {
+ AdornerPanel adorner = obj as AdornerPanel;
+ if (adorner != null) {
+ 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) {
- result = RunHitTest(this.Child, mousePosition, delegate { return HitTestFilterBehavior.Continue; });
- if (result != null && result.VisualHit != null) {
- customResult = new DesignPanelHitTestResult(result.VisualHit);
-
- ViewService viewService = _context.Services.View;
- DependencyObject obj = result.VisualHit;
- while (obj != null) {
- if ((customResult.ModelHit = viewService.GetModel(obj)) != null)
- break;
- obj = VisualTreeHelper.GetParent(obj);
- }
- if (customResult.ModelHit == null)
- {
- customResult.ModelHit = _context.RootItem;
+ if (continueHitTest && testDesignSurface) {
+ RunHitTest(
+ this.Child, mousePosition, delegate { return HitTestFilterBehavior.Continue; },
+ delegate(HitTestResult result) {
+ if (result != null && result.VisualHit != null && result.VisualHit is Visual) {
+ DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit);
+
+ ViewService viewService = _context.Services.View;
+ DependencyObject obj = result.VisualHit;
+ while (obj != null) {
+ if ((customResult.ModelHit = viewService.GetModel(obj)) != null)
+ break;
+ obj = VisualTreeHelper.GetParent(obj);
+ }
+ 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
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs
index ddba2f4b2a..59890e9a46 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasChildResizeSupport.cs
@@ -37,18 +37,15 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
}
///
- 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;
operation.Left = GetLeft(child);
operation.Top = GetTop(child);
operation.Right = operation.Left + GetWidth(child);
operation.Bottom = operation.Top + GetHeight(child);
- GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services.GetService(), this.ExtendedItem.View);
+ BeginPlacement();
}
static double GetLeft(UIElement element)
@@ -108,8 +105,49 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
///
public void FinishPlacement(PlacementOperation operation)
+ {
+ EndPlacement();
+ }
+
+ void BeginPlacement()
+ {
+ GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services, this.ExtendedItem.View);
+ }
+
+ void EndPlacement()
{
GrayOutDesignerExceptActiveArea.Stop(ref grayOut);
}
+
+ ///
+ public bool CanLeaveContainer(PlacementOperation operation)
+ {
+ return true;
+ }
+
+ ///
+ 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();
+ }
+
+ ///
+ public bool CanEnterContainer(PlacementOperation operation)
+ {
+ return true;
+ }
+
+ ///
+ public void EnterContainer(PlacementOperation operation)
+ {
+ this.ExtendedItem.Properties["Children"].CollectionElements.Add(operation.PlacedItem);
+ UpdatePlacement(operation);
+
+ BeginPlacement();
+ }
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs
index 8873a7466b..41ade54be5 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelSelectionHandler.cs
@@ -64,7 +64,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
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)
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
index 6f5cd46132..0690f2f9d5 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
@@ -96,7 +96,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
operation.Bottom = operation.Top;
break;
}
- operation.UpdatePlacement();
+ operation.CurrentContainerBehavior.UpdatePlacement(operation);
};
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/WindowResizeBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/WindowResizeBehavior.cs
new file mode 100644
index 0000000000..20b064fe4b
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/WindowResizeBehavior.cs
@@ -0,0 +1,105 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Windows;
+using ICSharpCode.WpfDesign.Extensions;
+
+namespace ICSharpCode.WpfDesign.Designer.Extensions
+{
+ ///
+ /// Supports resizing a Window.
+ ///
+ [ExtensionFor(typeof(Window))]
+ public class WindowResizeBehavior : BehaviorExtension, IRootPlacementBehavior
+ {
+ ///
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+ this.ExtendedItem.AddBehavior(typeof(IRootPlacementBehavior), this);
+ }
+
+ ///
+ public bool CanPlace(DesignItem child, PlacementType type, PlacementAlignment position)
+ {
+ return type == PlacementType.Resize &&
+ (position == PlacementAlignments.Right
+ || position == PlacementAlignments.BottomRight
+ || position == PlacementAlignments.Bottom);
+ }
+
+ ///
+ 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;
+ }
+
+ ///
+ 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);
+ }
+ }
+
+ ///
+ public void FinishPlacement(PlacementOperation operation)
+ {
+ }
+
+ ///
+ public bool CanLeaveContainer(PlacementOperation operation)
+ {
+ return false;
+ }
+
+ ///
+ public void LeaveContainer(PlacementOperation operation)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ public bool CanEnterContainer(PlacementOperation operation)
+ {
+ return false;
+ }
+
+ ///
+ public void EnterContainer(PlacementOperation operation)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs
index 8380dfbead..7b0e685449 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DragMoveMouseGesture.cs
+++ b/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
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;
operation.Left = startLeft + v.X;
operation.Right = startRight + v.X;
operation.Top = startTop + 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();
+ if (b != null && b.CanEnterContainer(operation)) {
+ operation.ChangeContainer(result.ModelHit);
+ return true;
+ }
+ return false;
+ }
+
protected override void OnMouseUp(object sender, MouseButtonEventArgs e)
{
if (operation != null) {
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/OptionService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/OptionService.cs
new file mode 100644
index 0000000000..2c13727ca2
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/OptionService.cs
@@ -0,0 +1,22 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+
+namespace ICSharpCode.WpfDesign.Designer.Services
+{
+ ///
+ /// Contains a set of options regarding the default designer components.
+ ///
+ public sealed class OptionService
+ {
+ ///
+ /// Gets/Sets whether the design surface should be grayed out while dragging/selection.
+ ///
+ public bool GrayOutDesignSurfaceExceptParentContainerWhenDragging = true;
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
index f186eff65b..eb9dc78f80 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
@@ -78,16 +78,19 @@
+
+
+
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 86c9c88791..11feed9544 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
+++ b/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(IErrorService), new DefaultErrorService());
this.Services.AddService(typeof(ViewService), new DefaultViewService(this));
+ this.Services.AddService(typeof(OptionService), new OptionService());
_componentService = new XamlComponentService(this);
this.Services.AddService(typeof(IComponentService), _componentService);
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs
index 75f9386ac6..edb4b37310 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs
+++ b/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 {
get { return (string)this.Properties["Name"].ValueOnInstance; }
set { this.Properties["Name"].SetValue(value); }
@@ -61,13 +65,13 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override event EventHandler NameChanged {
add {
#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
this.Properties["Name"].ValueChanged += value;
}
remove {
#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
this.Properties["Name"].ValueChanged -= value;
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelCollectionElementsCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelCollectionElementsCollection.cs
new file mode 100644
index 0000000000..d995052fae
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelCollectionElementsCollection.cs
@@ -0,0 +1,77 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+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
+ {
+ 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);
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
index 6ae6fdbbdb..fbdb1b3f00 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
@@ -19,6 +19,11 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
{
readonly XamlDesignItem _designItem;
readonly XamlProperty _property;
+ readonly XamlModelCollectionElementsCollection _collectionElements;
+
+ internal XamlDesignItem DesignItem {
+ get { return _designItem; }
+ }
public XamlModelProperty(XamlDesignItem designItem, XamlProperty property)
{
@@ -27,6 +32,9 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
this._designItem = designItem;
this._property = property;
+ if (property.IsCollection) {
+ _collectionElements = new XamlModelCollectionElementsCollection(this, property);
+ }
}
public override bool Equals(object obj)
@@ -70,7 +78,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override System.Collections.Generic.IList CollectionElements {
get {
- throw new NotImplementedException();
+ if (!IsCollection)
+ throw new DesignerException("Cannot access CollectionElements for non-collection properties.");
+ else
+ return _collectionElements;
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs
index 7a3fd70273..001c5fb2e8 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTestHelper.cs
@@ -78,7 +78,7 @@ namespace ICSharpCode.WpfDesign.Designer.Tests
static string ItemIdentity(DesignItem item)
{
- return item.Component.GetType().Name + " (" + item.GetHashCode() + ")";
+ return item.ComponentType.Name + " (" + item.GetHashCode() + ")";
}
protected void AssertLog(string expectedLog)
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs
index dd289e8778..ad7e3d6672 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/ModelTests.cs
@@ -10,6 +10,8 @@ using System.Text;
using System.IO;
using System.Xml;
using System.Diagnostics;
+using System.Windows;
+using System.Windows.Controls;
using NUnit.Framework;
using ICSharpCode.WpfDesign.Designer.Xaml;
using ICSharpCode.WpfDesign.Designer.Services;
@@ -75,5 +77,17 @@ namespace ICSharpCode.WpfDesign.Designer.Tests
AssertCanvasDesignerOutput(@"", button.Context);
AssertLog("");
}
+
+
+ [Test]
+ public void AddTextBoxToStackPanel()
+ {
+ DesignItem button = CreateCanvasContext("");
+ DesignItem canvas = button.Parent;
+ DesignItem textBox = canvas.Services.Component.RegisterComponentForDesigner(new TextBox());
+ canvas.Properties["Children"].CollectionElements.Add(textBox);
+ AssertCanvasDesignerOutput("\n", button.Context);
+ AssertLog("");
+ }
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs
new file mode 100644
index 0000000000..2bf9b3a8af
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionElementsCollection.cs
@@ -0,0 +1,66 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Generic;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ partial class XamlProperty
+ {
+ ///
+ /// The collection used by XamlProperty.CollectionElements
+ ///
+ sealed class CollectionElementsCollection : Collection
+ {
+ 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);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
index 27c4298a89..57559f77ce 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
@@ -58,6 +58,7 @@
GlobalAssemblyInfo.cs
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs
index f24714f0d5..aa46413965 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlMarkupValue.cs
@@ -29,6 +29,12 @@ namespace ICSharpCode.WpfDesign.XamlDom
return ((MarkupExtension)markupObject.Instance).ProvideValue(doc.ServiceProvider);
}
+ internal override void OnParentPropertyChanged()
+ {
+ base.OnParentPropertyChanged();
+ markupObject.ParentProperty = this.ParentProperty;
+ }
+
internal override void RemoveNodeFromParent()
{
markupObject.RemoveNodeFromParent();
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
index 5f6321b87c..561b9faec4 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
@@ -17,13 +17,13 @@ namespace ICSharpCode.WpfDesign.XamlDom
///
/// Describes a property on a .
///
- public sealed class XamlProperty
+ public sealed partial class XamlProperty
{
XamlObject parentObject;
XamlPropertyInfo propertyInfo;
XamlPropertyValue propertyValue;
- List collectionElements;
+ CollectionElementsCollection collectionElements;
bool isCollection;
static readonly IList emptyCollectionElementsArray = new XamlPropertyValue[0];
@@ -40,7 +40,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
} else {
if (propertyInfo.IsCollection) {
isCollection = true;
- collectionElements = new List();
+ 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.
///
public IList CollectionElements {
- get { return collectionElements != null ? collectionElements.AsReadOnly() : emptyCollectionElementsArray; }
+ get { return collectionElements ?? emptyCollectionElementsArray; }
}
///
@@ -217,7 +217,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
///
internal void ParserAddCollectionElement(XamlPropertyValue val)
{
- collectionElements.Add(val);
+ collectionElements.AddByParser(val);
val.ParentProperty = this;
}
@@ -270,7 +270,14 @@ namespace ICSharpCode.WpfDesign.XamlDom
///
public XamlProperty ParentProperty {
get { return _parentProperty; }
- internal set { _parentProperty = value; }
+ internal set {
+ _parentProperty = value;
+ OnParentPropertyChanged();
+ }
+ }
+
+ internal virtual void OnParentPropertyChanged()
+ {
}
internal abstract void RemoveNodeFromParent();
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
index 4c6059ddaf..91f45b540e 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
@@ -203,5 +203,27 @@ namespace ICSharpCode.WpfDesign.XamlDom
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);
+ }
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs
index 9fa8583294..6e2d6fab91 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/ExampleService.cs
@@ -34,6 +34,11 @@ namespace ICSharpCode.WpfDesign.XamlDom.Tests
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);
+ }
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs
index 8acd9496ae..06c4b8c906 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs
@@ -26,6 +26,13 @@ namespace ICSharpCode.WpfDesign
///
public abstract object Component { get; }
+ ///
+ /// 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.
+ ///
+ public abstract Type ComponentType { get; }
+
///
/// Gets the view used for the component.
///
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs
index c90c888ae1..8f937e7efa 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs
@@ -6,13 +6,14 @@
//
using System;
+using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.WpfDesign.Adorners;
namespace ICSharpCode.WpfDesign
{
///
- /// Describes the result of a call.
+ /// Describes the result of a call.
///
public struct DesignPanelHitTestResult : IEquatable
{
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs
index 11b8f279d8..2a540d8759 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs
@@ -112,7 +112,7 @@ namespace ICSharpCode.WpfDesign.Extensions
if (extendedItem.Component == null)
return emptyExtensionEntryArray;
else
- return GetExtensionEntries(extendedItem.Component.GetType());
+ return GetExtensionEntries(extendedItem.ComponentType);
}
ExtensionServer[] GetExtensionServersForItem(DesignItem item)
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs
index b6da3a4249..53795d0543 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs
@@ -27,13 +27,33 @@ namespace ICSharpCode.WpfDesign
///
/// Starts placement mode of the child element specified in the placement operation.
///
- void StartPlacement(PlacementOperation operation, out bool supportsRemoveFromContainer);
+ void StartPlacement(PlacementOperation operation);
///
/// Updates the placement of the element specified in the placement operation.
///
void UpdatePlacement(PlacementOperation operation);
+ ///
+ /// Gets if leaving this container is allowed for the specified operation.
+ ///
+ bool CanLeaveContainer(PlacementOperation operation);
+
+ ///
+ /// Remove the placed child from this container.
+ ///
+ void LeaveContainer(PlacementOperation operation);
+
+ ///
+ /// Gets if entering this container is allowed for the specified operation.
+ ///
+ bool CanEnterContainer(PlacementOperation operation);
+
+ ///
+ /// Let the placed child enter this container.
+ ///
+ void EnterContainer(PlacementOperation operation);
+
///
/// Finishes placement of a child element. This method is called both for aborted
/// and committed placement operations.
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs
index 57e11c0bfe..73da4a4062 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementOperation.cs
@@ -6,6 +6,7 @@
//
using System;
+using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
@@ -25,11 +26,8 @@ namespace ICSharpCode.WpfDesign
readonly IPlacementBehavior oldContainerBehavior;
DesignItem currentContainer;
IPlacementBehavior currentContainerBehavior;
- bool supportsRemoveFromContainer;
bool isAborted, isCommitted;
- //DesignItem newContainer;
-
#region Properties
///
/// The item being placed.
@@ -45,13 +43,6 @@ namespace ICSharpCode.WpfDesign
get { return type; }
}
- ///
- /// Gets if removing the placed item from the container is supported.
- ///
- public bool SupportsRemoveFromContainer {
- get { return supportsRemoveFromContainer; }
- }
-
///
/// Gets if the placement operation was aborted.
///
@@ -72,11 +63,46 @@ namespace ICSharpCode.WpfDesign
///
public double Left, Right, Top, Bottom;
+ ///
+ /// Gets the current container for the placement operation.
+ ///
+ public DesignItem CurrentContainer {
+ get { return currentContainer; }
+ }
+
+ ///
+ /// Gets the placement behavior for the current container.
+ ///
+ public IPlacementBehavior CurrentContainerBehavior {
+ get { return currentContainerBehavior; }
+ }
+
#endregion
- public void UpdatePlacement()
+ ///
+ /// Make the placed item switch the container.
+ /// This method assumes that you already have checked if changing the container is possible.
+ ///
+ 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();
+
+ Debug.Assert(currentContainerBehavior != null);
+ currentContainerBehavior.EnterContainer(this);
+ } catch (Exception ex) {
+ Debug.WriteLine(ex.ToString());
+ Abort();
+ throw;
+ }
}
#region Start
@@ -101,7 +127,7 @@ namespace ICSharpCode.WpfDesign
if (op.currentContainerBehavior == null)
throw new InvalidOperationException("Starting the operation is not supported");
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))
throw new InvalidOperationException("IPlacementBehavior.StartPlacement must set Left,Top,Right+Bottom to non-NAN values");
} catch {
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs
index b363df70ed..461bf3af58 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs
@@ -7,6 +7,7 @@
using System;
using System.ComponentModel;
+using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using System.Collections.Generic;
@@ -21,6 +22,34 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
readonly DesignItem item;
readonly List properties = new List();
+ #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 availableProperties = new Dictionary();
+
+ static string[] GetAvailableProperties(Type forType)
+ {
+ Debug.Assert(forType != null);
+ string[] result;
+ lock (availableProperties) {
+ if (availableProperties.TryGetValue(forType, out result))
+ return result;
+ }
+ List names = new List();
+ 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
+
///
/// Constructs a new DesignItemDataSource for the specified design item.
///
@@ -31,11 +60,8 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
this.item = item;
List designItemProperties = new List();
- foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(item.Component)) {
- if (!p.IsBrowsable) continue;
- if (p.IsReadOnly) continue;
- if (p.Name.Contains(".")) continue;
- designItemProperties.Add(item.Properties[p.Name]);
+ foreach (string name in GetAvailableProperties(item.ComponentType)) {
+ designItemProperties.Add(item.Properties[name]);
}
designItemProperties.AddRange(item.Properties);
@@ -99,7 +125,7 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// See
public string Type {
get {
- return item.Component.GetType().Name;
+ return item.ComponentType.Name;
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs
index 7bdd0cf023..c37fcabd8f 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs
@@ -85,6 +85,12 @@ namespace ICSharpCode.WpfDesign
///
DesignPanelHitTestResult HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface);
+ ///
+ /// Performs a hit test on the design surface, raising for each match.
+ /// Hit testing continues while the callback returns true.
+ ///
+ void HitTest(MouseEventArgs e, bool testAdorners, bool testDesignSurface, Predicate callback);
+
// The following members were missing in , but
// are supported on the DesignPanel: