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 @@ @@ -29,7 +29,9 @@
<Button>CB</Button>
</Canvas>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Canvas Height="50">
<Button>Button 2</Button>
</Canvas>
<TabControl Width="300" MinHeight="100">
<TabItem Header="Page 1"><StackPanel><Button>a</Button></StackPanel> </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 @@ @@ -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 @@ -63,9 +61,30 @@ namespace StandaloneDesigner
}
}
ICollection<DesignItem> 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<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; @@ -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 @@ -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 @@ -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<IDesignPanel>();
OptionService optionService = services.GetService<OptionService>();
if (designPanel != null && grayOut == null && optionService != null && optionService.GrayOutDesignSurfaceExceptParentContainerWhenDragging) {
grayOut = new GrayOutDesignerExceptActiveArea();
grayOut.designPanel = designPanel;
grayOut.adornerPanel = new AdornerPanel();

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

@ -43,6 +43,17 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -43,6 +43,17 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
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>
/// Specifies the icon to use.
/// </summary>
@ -60,6 +71,16 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -60,6 +71,16 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
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>
/// Gets or sets the resize mode.
/// </summary>
@ -109,6 +130,24 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -109,6 +130,24 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
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>
/// This property has no effect. (for compatibility with <see cref="Window"/> only).
/// </summary>

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

@ -38,17 +38,10 @@ namespace ICSharpCode.WpfDesign.Designer @@ -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 @@ -62,65 +55,81 @@ namespace ICSharpCode.WpfDesign.Designer
return HitTestFilterBehavior.Continue;
}
DesignPanelHitTestResult _lastHitTestResult;
/// <summary>
/// Performs a custom hit testing lookup for the specified mouse event args.
/// </summary>
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)
/// <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) {
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

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

@ -37,18 +37,15 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -37,18 +37,15 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
}
/// <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;
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<IDesignPanel>(), this.ExtendedItem.View);
BeginPlacement();
}
static double GetLeft(UIElement element)
@ -108,8 +105,49 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -108,8 +105,49 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
/// <inherits/>
public void FinishPlacement(PlacementOperation operation)
{
EndPlacement();
}
void BeginPlacement()
{
GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services, this.ExtendedItem.View);
}
void EndPlacement()
{
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 @@ -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)

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

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

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

@ -0,0 +1,105 @@ @@ -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 @@ -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<IPlacementBehavior>();
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) {

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

@ -0,0 +1,22 @@ @@ -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 @@ @@ -78,16 +78,19 @@
<Compile Include="Extensions\TabItemClickableExtension.cs" />
<Compile Include="Extensions\TopLeftContainerDragHandle.cs" />
<Compile Include="Extensions\ResizeThumbExtension.cs" />
<Compile Include="Extensions\WindowResizeBehavior.cs" />
<Compile Include="Func.cs" />
<Compile Include="ServiceRequiredException.cs" />
<Compile Include="Services\ClickOrDragMouseGesture.cs" />
<Compile Include="Services\DragMoveMouseGesture.cs" />
<Compile Include="Services\ErrorService.cs" />
<Compile Include="Services\OptionService.cs" />
<Compile Include="Services\SelectionService.cs" />
<Compile Include="Services\ToolService.cs" />
<Compile Include="Services\UndoService.cs" />
<Compile Include="Services\ViewService.cs" />
<Compile Include="DesignSurface.cs" />
<Compile Include="Xaml\XamlModelCollectionElementsCollection.cs" />
<Compile Include="Xaml\XamlComponentService.cs" />
<Compile Include="Xaml\XamlDesignContext.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 @@ -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);

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

@ -46,6 +46,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -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 @@ -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;
}

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

@ -0,0 +1,77 @@ @@ -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 @@ -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 @@ -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 @@ -70,7 +78,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override System.Collections.Generic.IList<DesignItem> CollectionElements {
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 @@ -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)

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

@ -10,6 +10,8 @@ using System.Text; @@ -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 @@ -75,5 +77,17 @@ namespace ICSharpCode.WpfDesign.Designer.Tests
AssertCanvasDesignerOutput(@"<Button Width=""100"" Height=""200"" />", button.Context);
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 @@ @@ -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 @@ @@ -58,6 +58,7 @@
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="CollectionElementsCollection.cs" />
<Compile Include="XamlConstants.cs" />
<Compile Include="XamlDocument.cs" />
<Compile Include="XamlLoadException.cs" />

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

@ -29,6 +29,12 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -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();

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

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

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

@ -203,5 +203,27 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -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);
}
}
}

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

@ -34,6 +34,11 @@ namespace ICSharpCode.WpfDesign.XamlDom.Tests @@ -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);
}
}
}

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

@ -26,6 +26,13 @@ namespace ICSharpCode.WpfDesign @@ -26,6 +26,13 @@ namespace ICSharpCode.WpfDesign
/// </summary>
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>
/// Gets the view used for the component.
/// </summary>

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

@ -6,13 +6,14 @@ @@ -6,13 +6,14 @@
// </file>
using System;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.WpfDesign.Adorners;
namespace ICSharpCode.WpfDesign
{
/// <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>
public struct DesignPanelHitTestResult : IEquatable<DesignPanelHitTestResult>
{

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

@ -112,7 +112,7 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -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)

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

@ -27,13 +27,33 @@ namespace ICSharpCode.WpfDesign @@ -27,13 +27,33 @@ namespace ICSharpCode.WpfDesign
/// <summary>
/// Starts placement mode of the child element specified in the placement operation.
/// </summary>
void StartPlacement(PlacementOperation operation, out bool supportsRemoveFromContainer);
void StartPlacement(PlacementOperation operation);
/// <summary>
/// Updates the placement of the element specified in the placement operation.
/// </summary>
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>
/// Finishes placement of a child element. This method is called both for aborted
/// and committed placement operations.

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

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
@ -25,11 +26,8 @@ namespace ICSharpCode.WpfDesign @@ -25,11 +26,8 @@ namespace ICSharpCode.WpfDesign
readonly IPlacementBehavior oldContainerBehavior;
DesignItem currentContainer;
IPlacementBehavior currentContainerBehavior;
bool supportsRemoveFromContainer;
bool isAborted, isCommitted;
//DesignItem newContainer;
#region Properties
/// <summary>
/// The item being placed.
@ -45,13 +43,6 @@ namespace ICSharpCode.WpfDesign @@ -45,13 +43,6 @@ namespace ICSharpCode.WpfDesign
get { return type; }
}
/// <summary>
/// Gets if removing the placed item from the container is supported.
/// </summary>
public bool SupportsRemoveFromContainer {
get { return supportsRemoveFromContainer; }
}
/// <summary>
/// Gets if the placement operation was aborted.
/// </summary>
@ -72,11 +63,46 @@ namespace ICSharpCode.WpfDesign @@ -72,11 +63,46 @@ namespace ICSharpCode.WpfDesign
/// </summary>
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
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
@ -101,7 +127,7 @@ namespace ICSharpCode.WpfDesign @@ -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 {

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

@ -7,6 +7,7 @@ @@ -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 @@ -21,6 +22,34 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
readonly DesignItem item;
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>
/// Constructs a new DesignItemDataSource for the specified design item.
/// </summary>
@ -31,11 +60,8 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -31,11 +60,8 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
this.item = item;
List<DesignItemProperty> designItemProperties = new List<DesignItemProperty>();
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 @@ -99,7 +125,7 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
public string Type {
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 @@ -85,6 +85,12 @@ namespace ICSharpCode.WpfDesign
/// </summary>
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
// are supported on the DesignPanel:

Loading…
Cancel
Save