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(@"